d3js滚动可见性 - 饼图的系列动画

时间:2018-04-19 08:45:11

标签: javascript d3.js

enter image description here

我正在开发一个d3应用程序 - 带有饼图 - 我想获得动画onload和号召性用语。就像在滚动期间图表变得可见时一样。

馅饼段围绕中心枢轴生长。因此补间或捕捉到其他部分,如接力赛

http://jsfiddle.net/pg886/192/

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://d3js.org/d3.v3.min.js"></script>

<div class="piechart" data-role="piechart" data-width=400 data-height=400 data-radius=30  data-innerradius=20
    data-data=x>
</div>

<style>
    .piechart{
      /*border: 1px solid black;*/  
      /*text-align: center;
      font-size: 12px;*/
    }
</style>

<script>

$( document ).ready(function() {
        console.log("test")

       var $this = $('.piechart');

        var data = [{
            "label": "Apples",
            "value": 100
        },
        {
            "label": "Pears",
            "value": 120
        },
        {
            "label": "Bananas",
            "value": 20
        }];


        var w = $this.data("width");
        var h = $this.data("height");
        var ir = $this.data("innerradius");
        var r = $this.data("radius");

        function colores_google(n) {
            var colores_g = ["#f7b363", "#448875", "#c12f39", "#2b2d39", "#f8dd2f"];
            //var colores_g = ["#47abd5", "#005a70", "#f5a0a3", "#ff7276", "#a9a19c", "#d0743c", "#ff8c00"];
            return colores_g[n % colores_g.length];
        }

        var radius = Math.min(w, h) / 4;


        var arc = d3.svg.arc()
            .outerRadius(radius - 10)
            .innerRadius(0);

        var labelArc = d3.svg.arc()
            .outerRadius(radius - r)
            .innerRadius(radius - ir);    

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



        var chart = d3.select('.piechart').append("svg")
                        .attr("class", "chart")
                        .attr("width", w)
                        .attr("height", h)
                        .attr("transform", "translate(0,0)");

        var piechart = chart              
                        .append("g")
                        .attr("class", "piechart")
                        .attr("width", (radius*2))
                        .attr("transform", "translate(0,"+h/4+")");

        var path_group = piechart.append("g")
            .attr("class", "path_group")
            .attr("transform", "translate(90," + ((h / 4) - 20) + ")");


        var padding = 45;
        var legendPaddingTop = 30;
        var legend = chart.append("g")
            .attr("class", "legend")
            .attr("width", w/2)
            .attr("height", h)
            .attr("transform", "translate(" + (w - 50) + "," + (h / 4) + ")");  


        var label_group = legend.append("svg:g")
            .attr("class", "label_group")
            .attr("transform", "translate(" + (-(w / 3) + 20) + "," + 0 + ")");

        var legend_group = legend.append("svg:g")
            .attr("class", "legend_group")
            .attr("transform", "translate(" + (-(w / 3) - 100) + "," + 0 + ")");


        var g = path_group.selectAll(".arc")
            .data(pie(data))
            .enter().append("g")
            .attr("class", "arc");

        g.append("path")
            .attr("d", arc)
            .style("fill", function(d, i) { 
                return colores_google(i);
            });


        var legendHeight = legendPaddingTop;
        var ySpace = 18;

        //draw labels                   
        var labels = label_group.selectAll("text.labels")
            .data(data);

        labels.enter().append("svg:text")
            .attr("class", "labels")
            .attr("dy", function(d, i) {                  
                legendHeight+=ySpace;   
              return (ySpace * i) + 4;
            })
            .attr("text-anchor", function(d) {
              return "start";
            })
            .text(function(d) {
              return d.label;
            });

        labels.exit().remove();
        //draw labels


        //draw legend
        var legend = legend_group.selectAll("circle").data(data);

        legend.enter().append("svg:circle")
            .attr("cx", 100)
            .attr("cy", function(d, i) {
              return ySpace * i;
            })
            .attr("r", 7)
            .attr("width", 18)
            .attr("height", 18)
            .style("fill", function(d, i) {
              return colores_google(i);
            });

        legend.exit().remove();
        //draw legend

        //reset legend height
        //console.log("optimum height for legend", legendHeight);
        $this.find('.legend').attr("height", legendHeight);

        function type(d) {
          d.value = +d.value;
          return d;
        }

});

</script>

1 个答案:

答案 0 :(得分:3)

所以你可以很容易地实现这一点,并且有几个块可以帮助你。

Arc Tween首先,此块为您提供了如何补间弧的示例。基本上你不能自动获得,所以你必须编写自己的attrTween函数。幸运的是,这很简单,Mike Bostock在那里给出了一个非常好的例子。

这是一个代码示例 - 但链接提供了一个非常好的详细描述。

.attrTween("d", function(d) {
    var interpolate = d3.interpolate(d.endAngle, newAngle);    
    return function(t) {
      d.endAngle = interpolate(t);
      return arc(d);
    };
}   

接下来你需要这样的东西Donut with transitions。这实际上是您尝试前往的最终结果。这种效果很容易实现,您需要做的就是正确设置角度和时间。

角度:所以,您希望endAnglestartAngle在开始时都是相同的(应该是endAngle的{​​{1}}值上一个细分或第一个细分的0

计时:您希望在开始下一个动画之前完成1个动画,只需延迟它们即可。您可以看到使用此代码段完成的操作:

.transition()
.delay(function(d,i) { return i * 500; })
.duration(500)
.attrTween(...)

&#13;
&#13;
const dataset = [
	{ age: "<5", population: 2704659 },
  { age: "5-13", population: 4499890 },
  { age: "14-17", population: 2159981 },
  { age: "18-24", population: 3853788 },
  { age: "25-44", population: 14106543 },
  { age: "45-64", population: 8819342 },
  { age: "≥65", population: 612463 },
];
const TIME = 2000 / dataset.length;

const color = d3.scaleOrdinal(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);

const pie = d3.pie()
    .sort(null)
    .value(function(d) { return d.population; });
    
const path = d3.arc()
    .innerRadius(0)
    .outerRadius(350);
    
d3.select("#container")
  .selectAll(".arc")
  .data(pie(dataset))
  .enter()
  .append("g")
  .attr("class", "arc")
  .append("path")
  .attr("fill", function(d) { return color(d.data.age); })
  .transition()
  .duration(TIME)
  .ease(d3.easeLinear)
  .delay(function(d, i) { return i * TIME; })
  .attrTween("d", function(d) {
     // Note the 0.1 to prevent errors generating the path
     const angleInterpolation = d3.interpolate(d.startAngle + 0.1, d.endAngle);
     return function(t) {
        d.endAngle = angleInterpolation(t);
        return path(d);
     }
  });
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="800" height="800">
   <g id="container" transform="translate(400, 400)"></g>
</svg>
&#13;
&#13;
&#13;