d3.js可重用的饼图与动态更新

问题描述:

我试图创建一个可重用的饼图与动态转换作为学习任务。我正在工作的d3.js resuable组件电子书由Chris Viau。
我所遇到的问题基本上是它不更新,但创建多个饼图。我想知道,如果我不明白d3.dispatch如何工作,或者我是否以一种方式饼干应该工作的东西。它会创建多个圆形,而不是动态更新带有随机值的单个饼图。

I'm trying to create a reusable pie chart with dynamic transitions as a learning task. I'm working off of the d3.js resuable components e-book by Chris Viau. The problem I'm having is basically its not updating, but creating multiple pie charts. I'm wondering if I'm not understanding how d3.dispatch works or whether I've messed something up in the way the pie char should work. It creates multiple circles instead of dynamically updating a single pie chart with random values.

这里是我的jsfiddle。

here is my jsfiddle.

http://jsfiddle.net/seoulbrother/Upcr5 /

感谢!

js代码如下:

d3.edge = {};

d3.edge.donut = function module() {

    var width = 460,
        height = 300,
        radius = Math.min(width, height) / 2;

    var color = d3.scale.category20();


   var dispatch = d3.dispatch("customHover");
   function graph(_selection) {
       _selection.each(function(_data) {    
            var pie = d3.layout.pie()
                .value(function(_data) { return _data; })
                .sort(null);

            var arc = d3.svg.arc()
                .innerRadius(radius - 100)
                .outerRadius(radius - 50);

            if (!svg){
                var svg = d3.select(this).append("svg")
                    .attr("width", width)
                    .attr("height", height)
                    .append("g")
                    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
            }
            var path = svg.selectAll("path")
                .data(pie)
              .enter().append("path")
                .attr("fill", function(d, i) { return color(i); })
                .attr("d", arc)
                .each(function(d) {this._current = d;} );

            path.transition()
                  .ease("elastic")
                  .duration(750)
                  .attrTween("d", arcTween);              

            function arcTween(a) {
              var i = d3.interpolate(this._current, a);
              this._current = i(0);
              return function(t) {
                return arc(i(t));
              };
            }
        });

    }
    d3.rebind(graph, dispatch, "on");
    return graph;
}

donut = d3.edge.donut();
var data = [1, 2, 3, 4];
var container = d3.select("#viz").datum(data).call(donut);

function update(_data) {
    data = d3.range(~~(Math.random() * 20)).map(function(d, i) {
        return ~~(Math.random() * 100);
    });
    container.datum(data).transition().ease("linear").call(donut);
}

update();
setTimeout( update, 1000);


多个SVG出现的主要原因是,不检查是否有一个已经正确。您依赖于定义的变量 svg ,但只有在检查它是否被定义后才定义。

The main reason for multiple SVGs appearing is that you're not checking if there is one already correctly. You're relying on the variable svg being defined, but define it only after checking whether it is defined.

更好的方法是选择您要查找的元素,并检查该选择是否为空:

The better way is to select the element you're looking for and check whether that selection is empty:

var svg = d3.select(this).select("svg > g");
if (svg.empty()){ // etc

除了输入选择之外,还可以在代码中处理更新和退出选择。完成jsfiddle 这里

In addition, you need to handle the update and exit selections in your code in addition to the enter selection. Complete jsfiddle here.