block by HarryStevens e1acaf628b1693f1b32e5f2e1a7f73fb

Pie Update Pattern

Full Screen

Use D3’s general update pattern to animate pie chart transitions. I got the arcTween function from this block by Mike Bostock (so you know it’s good).

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <script src="https://unpkg.com/jeezy/lib/jeezy.min.js"></script>
    <script>

    var alphabet = "abcdef".split("");

    var margin = {top: 10, bottom: 10, left: 10, right: 10},
      width = window.innerWidth - margin.left - margin.right,
      height = window.innerHeight - margin.top - margin.bottom,
      radius = Math.min(width, height) / 2;

    var svg = d3.select("body").append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
      .append("g")
        .attr("transform", "translate(" + ((width / 2) + margin.left) + "," + ((height / 2) + margin.top) + ")");

    var color = d3.scaleOrdinal(["#66c2a5","#fc8d62","#8da0cb","#e78ac3","#a6d854","#ffd92f"])

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

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

    redraw(randomData(alphabet));

    d3.interval(function(){
      redraw(randomData(alphabet));  
    }, 2000)

    function redraw(data){

      // join
      var arcs = svg.selectAll(".arc")
          .data(pie(data), function(d){ return d.data.name; });

      // update
      arcs 
        .transition()
          .duration(1500)
          .attrTween("d", arcTween);

      // enter
      arcs.enter().append("path")
        .attr("class", "arc")
        .attr("fill", function(d, i) { return color(i); })
        .attr("d", arc)
        .each(function(d) { this._current = d; });

    }

    // Store the displayed angles in _current.
    // Then, interpolate from _current to the new angles.
    // During the transition, _current is updated in-place by d3.interpolate.
    function arcTween(a) {
      console.log(this._current);
      var i = d3.interpolate(this._current, a);
      this._current = i(0);
      return function(t) {
        return arc(i(t));
      };
    }

    function randomData(data){
      return data.map(function(d){
        return {
          name: d,
          value: jz.num.randBetween(1, 10)
        }
      });
    }

    </script>
  </body>
</html>