D3圆环图进入转型 [英] D3 Donut Chart Enter with Transition

查看:102
本文介绍了D3圆环图进入转型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have been working from this D3 block http://bl.ocks.org/dbuezas/9306799.

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

I have the code pretty much the way I want it. Except the chart only animates when part of the data set is shared. If the the dataset contains no labels in common, the graph is simply swapped out. How do I make it do a growing arc transition from the beginning so the user always knows when new data is presented? I am taking this snippet out of an angular directive so it might not stand quite on its own, 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();

        };


推荐答案

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

The heart of the problem is there's no starting point for entering slices to tween from. That said, I'd really simplify the tween code a bit:

  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));
      };
    })






完整工作代码:


Full working code:

<!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>

这篇关于D3圆环图进入转型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆