D3 甜甜圈过渡,d,i 变得不确定

D3 Donut transition, d,i getting undefine

        var arcMin = 75;        // inner radius of the first arc
        var arcWidth = 25;      // width
        var arcPad = 10;         // padding between arcs

        var arc = d3.arc()
                  .innerRadius(function(d, i) {
                    return  arcMin + i*(arcWidth) + arcPad;
                  })
                  .outerRadius(function(d, i) {
                    return arcMin + (i+1)*(arcWidth);
                  })
                  .startAngle(0 * (PI/180))
                  .endAngle(function(d, i) {
//                    console.log(d);       <----getting undefine under attrTween Call
                    return 2*PI*d.value/100;
                  });

        var path = g.selectAll('path')
          .data(pie(dataset))
          .enter()
          .append('path')
          .attr('d', arc)
          .attr('fill', function(d, i) { 
            return d.data.color;
          })
          .transition()
          .delay(function(d, i) {
            return i * 800;
          });
//          .attrTween('d', function(d) {
//            // This part make my chart disapear
//             var i = d3.interpolate(d.startAngle, d.endAngle);
//             return function(t) {
//               d.endAngle = i(t);
//               return arc(d);
//             }
//            // This part make my chart disapear
//          });

arc(d) 总是 return "M0,0Z"..

我发现原因是在arcTween下调用arc时,所有d,i return undefine。我该如何解决这个问题。

代码在这里:https://jsfiddle.net/m8oupfne/3/

最终产品:

两件事:

  1. 乍一看你的 attrTween 函数不起作用,因为你的 arc 函数同时依赖于 d,i 而你只传递 d

  2. 但是,解决这个问题并不能使您的图表很好地过渡?为什么?因为你的 arc 函数似乎没有任何意义。您使用 pie 计算角度,然后在 arc 函数中覆盖它们。每次调用 arc 函数都会计算出相同的 endAngle,因为它基于 d.value.

因此,如果您想要自定义角度计算,根本不要调用 pie,而是预先计算您的 endAngle 不要 在你的 arc 函数中完成。

arc 变为:

var arc = d3.arc()
  .innerRadius(function(d, i) {
    return  arcMin + i*(arcWidth) + arcPad;
  })
  .outerRadius(function(d, i) {
    return arcMin + (i+1)*(arcWidth);
  });

预计算数据:

dataset.forEach(function(d,i){
  d.endAngle = 2*PI*d.value/100;
  d.startAngle = 0;
});

arcTween 变为:

.attrTween('d', function(d,i) {
  var inter = d3.interpolate(d.startAngle, d.endAngle);             
  return function(t) {
    d.endAngle = inter(t);
    return arc(d,i);
  }
});

运行代码:

 (function(d3) {
        'use strict';

 
        var dataset = [
          { label: 'a', value: 88, color : '#898989'},
          { label: 'b', value: 56 , color : '#898989'},
          { label: 'c', value: 20 , color : '#FDD000'},
          { label: 'd', value: 46 , color : '#898989'},
        ];
      
        var PI = Math.PI;
        var arcMin = 75;        // inner radius of the first arc
        var arcWidth = 25;      // width
        var arcPad = 10;         // padding between arcs
        var arcBgColor = "#DCDDDD";
      
        var width = 360;
        var height = 360;
        var radius = Math.min(width, height) / 2;
        var donutWidth = 15;                            // NEW

        var svg = d3.select('#canvas')
          .append('svg')
          .attr('width', width)
          .attr('height', height);
      
       var gBg = svg.append('g').attr('transform', 'translate(' + (width / 2) + 
            ',' + (height / 2) + ')');
       var g = svg.append('g')
          .attr('transform', 'translate(' + (width / 2) + 
            ',' + (height / 2) + ')');
    
        var arc = d3.arc()
                  .innerRadius(function(d, i) {
                    return  arcMin + i*(arcWidth) + arcPad;
                  })
                  .outerRadius(function(d, i) {
                    return arcMin + (i+1)*(arcWidth);
                  });

        var arcBg = d3.arc()
                  .innerRadius(function(d, i) {
                    return  arcMin + i*(arcWidth) + arcPad;
                  })
                  .outerRadius(function(d, i) {
                    return arcMin + (i+1)*(arcWidth);
                  })
                  .startAngle(0 * (PI/180))
                  .endAngle(function(d, i) {
                    return 2*PI;
                  });
   
        var pie = d3.pie()
          .value(function(d) { return d.value; })
          .sort(null);

      
        var pathBg = gBg.selectAll('path')
          .data(pie(dataset))
          .enter()
          .append('path')
          .attr('d', arcBg)
          .attr('fill', arcBgColor );
          
        dataset.forEach(function(d,i){
         d.endAngle = 2*PI*d.value/100;
          d.startAngle = 0;
        });
        
        var path = g.selectAll('path')
          .data(dataset)
          .enter()
          .append('path')
          .attr('fill', function(d, i) { 
            return d.color;
          })
          .transition()
          .duration(800)
          .delay(function(d, i) {
           return i * 800;
          })
          .attrTween('d', function(d,i) {
             var inter = d3.interpolate(d.startAngle, d.endAngle);             
             return function(t) {
               d.endAngle = inter(t);
               return arc(d,i);
             }
          });
  
      })(window.d3);
   
<script src="https://cdn.jsdelivr.net/jquery/2.1.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/d3js/4.6.0/d3.min.js"></script>
   <div id="canvas"></div>