D3圆环图输入转换

时间:2015-12-09 01:07:11

标签: javascript d3.js

我一直在使用这个D3区块http://bl.ocks.org/dbuezas/9306799

我的代码几乎就像我想要的那样。除了图表之外,仅在共享部分数据集时动画。如果数据集不包含任何共同的标签,则只需交换图表。如何让它从一开始就进行不断增长的弧转换,以便用户始终知道何时出现新数据?我正在从一个角度指令中取出这个片段,所以它可能不会独立,fyi。

        var padding = 0;
        var height = 350;
        var width = 450;  

        var svg = d3.select("body")
            .append("svg")
            .attr('viewBox','0 0 '+ width  +' '+ height)
            .attr('preserveAspectRatio','xMinYMin')
            .append("g")


        svg.append("g")
            .attr("class", "slices");
        svg.append("g")
            .attr("class", "labels");
        svg.append("g")
            .attr("class", "lines");


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

        var pie = d3.layout.pie()
            .sort(null)
            .value(function(d) {
                return d.value;
            });

        var arc = d3.svg.arc()
            .outerRadius(radius * 0.8)
            .innerRadius(radius * 0.6);

        var outerArc = d3.svg.arc()
            .innerRadius(radius * 0.9)
            .outerRadius(radius * 0.9);

        svg.attr("transform", "translate(" + width / 2 + "," + element.parent().height() / 2 + ")");

        var key = function(d){ return d.data.label; };

        var color = d3.scale.category20b();

        var dataset = [
            {
                label: "SUPPLY",
                percentage: "22",
                value: 10621
            },
            {
                label: "FROZEN",
                percentage: "22",
                value: 17621
            }
        ];


        render(dataset);


        function render(data) {

            /* ------- PIE SLICES -------*/
            var slice = svg.select(".slices").selectAll("path.slice")
                .data(pie(data), key);

            slice.enter()
                .insert("path")
                .style("fill", function(d) { return color(d.data.label); })
                .attr("class", "slice");

            slice       
                .transition().duration(1000)
                .attrTween("d", function(d) {
                    this._current = this._current || d;
                    var interpolate = d3.interpolate(this._current, d);
                    this._current = interpolate(0);
                    return function(t) {
                        return arc(interpolate(t));
                    };
                })

            slice.exit()
                .remove();

            /* ------- TOOLTIP  -----------*/

            var tooltip = d3.select(element.parent()[0])                               
                .append('div')                                                
                .attr('class', 'donut-tip bodhi-tooltip');

            tooltip.append('div')
                .attr('class', 'bodhi-tooltip-text');

            slice.on('mouseover', function(d) {
                tooltip.select('.bodhi-tooltip-text').html(d.data.label + '</br>' + d.data[scope.tooltipKeyOne] + "%" + '</br>' + "$" + (d.data.total / 100).toFixed(2));
                tooltip.style('display', 'table');
            });

            slice.on('mouseout', function(d) {
                tooltip.style('display', 'none');
            });    

            /* ------- TEXT LABELS -------*/

            var text = svg.select(".labels").selectAll("text")
                .data(pie(data), key);

            text.enter()
                .append("text")
                .attr("dy", ".35em")
                .text(function(d) {
                    return d.data.label;
                });

            function midAngle(d){
                return d.startAngle + (d.endAngle - d.startAngle)/2;
            }

            text.transition().duration(1000)
                .attrTween("transform", function(d) {
                    this._current = this._current || d;
                    var interpolate = d3.interpolate(this._current, d);
                    this._current = interpolate(0);
                    return function(t) {
                        var d2 = interpolate(t);
                        var pos = outerArc.centroid(d2);
                        return "translate("+ pos +")";
                    };
                })
                .styleTween("text-anchor", function(d){
                    this._current = this._current || d;
                    var interpolate = d3.interpolate(this._current, d);
                    this._current = interpolate(0);
                    return function(t) {
                        var d2 = interpolate(t);
                        return midAngle(d2) < Math.PI ? "start":"end";
                    };
                });

            text.exit()
                .remove();

        };

1 个答案:

答案 0 :(得分:3)

问题的核心在于输入切片没有起点。也就是说,我真的简化了补间代码:

  slice.enter()
    .insert("path")
    .style("fill", function(d) {
      return color(d.data.label);
    })
    .attr("class", "slice")
    .each(function(d){
      this._current = { //<-- give the entering slices a starting point
        startAngle: d.startAngle, //<-- have them "grow" from nothing
        endAngle: d.startAngle
      }; 
    });

  slice
    .transition().duration(1000)
    .attrTween("d", function(d) {
      var endAt = { //<-- have the arc end where it's supposed to
        startAngle: d.startAngle, 
        endAngle: d.endAngle
      };
      var interpolate = d3.interpolate(this._current, endAt);
      this._current = endAt; //<-- store this for next cycle
      return function(t) {
        return arc(interpolate(t));
      };
    })

完整的工作代码:

&#13;
&#13;
<!DOCTYPE html>
<html>

<head>
  <script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
</head>

<body>
  <script>
    var padding = 0;
    var height = 350;
    var width = 450;

    var svg = d3.select("body")
      .append("svg")
      .attr('viewBox', '0 0 ' + width + ' ' + height)
      .attr('preserveAspectRatio', 'xMinYMin')
      .append("g")


    svg.append("g")
      .attr("class", "slices");
    svg.append("g")
      .attr("class", "labels");
    svg.append("g")
      .attr("class", "lines");


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

    var pie = d3.layout.pie()
      .sort(null)
      .value(function(d) {
        return d.value;
      });

    var arc = d3.svg.arc()
      .outerRadius(radius * 0.8)
      .innerRadius(radius * 0.6);

    var outerArc = d3.svg.arc()
      .innerRadius(radius * 0.9)
      .outerRadius(radius * 0.9);

    svg.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

    var key = function(d) {
      return d.data.label;
    };

    var color = d3.scale.category20b();

    update();

    setInterval(update, 2000);

    function update() {
      
      var someData = [];
      for (var i = 0; i < Math.random() * 10; i++){
          someData.push({
            label: "Slice " + i,
            percentage: "22",
            value: Math.random()
          });
      }
      render(someData);
    }

    function render(data) {

      /* ------- PIE SLICES -------*/
      var slice = svg.select(".slices").selectAll("path.slice")
        .data(pie(data), key);

      slice.enter()
        .insert("path")
        .style("fill", function(d) {
          return color(d.data.label);
        })
        .attr("class", "slice")
        .each(function(d){
          this._current = {
            startAngle: d.startAngle, 
            endAngle: d.startAngle
          };
        });
        
      slice
        .transition().duration(1000)
        .attrTween("d", function(d) {
          var endAt = {
            startAngle: d.startAngle, 
            endAngle: d.endAngle
          };
          var interpolate = d3.interpolate(this._current, endAt);
          this._current = endAt;
          return function(t) {
            return arc(interpolate(t));
          };
        })

      slice.exit()
        .remove();

      /* ------- TEXT LABELS -------*/

      var text = svg.select(".labels").selectAll("text")
        .data(pie(data), key);

      text.enter()
        .append("text")
        .attr("dy", ".35em")
        .text(function(d) {
          return d.data.label;
        });

      function midAngle(d) {
        return d.startAngle + (d.endAngle - d.startAngle) / 2;
      }

      text.transition().duration(1000)
        .attrTween("transform", function(d) {
          this._current = this._current || d;
          var interpolate = d3.interpolate(this._current, d);
          this._current = interpolate(0);
          return function(t) {
            var d2 = interpolate(t);
            var pos = outerArc.centroid(d2);
            return "translate(" + pos + ")";
          };
        })
        .styleTween("text-anchor", function(d) {
          this._current = this._current || d;
          var interpolate = d3.interpolate(this._current, d);
          this._current = interpolate(0);
          return function(t) {
            var d2 = interpolate(t);
            return midAngle(d2) < Math.PI ? "start" : "end";
          };
        });

      text.exit()
        .remove();

    };
  </script>
</body>

</html>
&#13;
&#13;
&#13;