简体   繁体   English

D3甜甜圈图带有过渡输入

[英]D3 Donut Chart Enter with Transition

I have been working from this D3 block http://bl.ocks.org/dbuezas/9306799 . 我一直在D3区块http://bl.ocks.org/dbuezas/9306799中工作

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> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM