d3.js:如何修复我的交互式饼图?

时间:2017-10-08 12:42:26

标签: d3.js data-visualization interactive

我正在努力教自己如何在d3.js中进行交互式可视化,目前正在通过Elijah Meeks的D3.js In Action进行工作。我正在尝试使用三个按钮使他的饼图示例交互。我的补间做错了 - 我正在尝试保存当前显示的馅饼,以便转换到它和新选择的馅饼之间。但是,我当前的馅饼一直在重置为最初的馅饼。我认为这可能很简单,但我无法弄清楚我做错了什么。

有人可以告诉我要改变什么来使我的过渡工作吗?为了证明这个问题:

  1. 运行以下代码,
  2. 点击“统计2”按钮,
  3. 再次点击“统计2”按钮 - 您将看到饼图重置为“统计1”,然后平稳过渡到“统计2”。
  4. $ awk 'index($0,"/*"){f=1} index($0,"*/"){f=0} !f && /alex/{print}' file
    alex is a nice man
    
    .as-console-wrapper { max-height: 20% !important;}

1 个答案:

答案 0 :(得分:1)

选择后,您永远不会将currentPie的状态设置为新状态。我已经为转换添加了.on('end',处理程序来设置此状态:

.on('end', function(){
  currentPie = newPie;
});

运行代码:



<html>

  <head>
    <script src="https://d3js.org/d3.v4.min.js"></script>
  </head>

  <body>
    <div id="viz">
      <button id="0"> Stat 1 </button>
      <button id="1"> Stat 2 </button>
      <button id="2"> Stat 3 </button>
      <br />
      <svg style="width:1000px;height:500px;border:1px lightgray solid;"></svg>
    </div>
    <script>
    var obj = [{name: "a",stat1: 10,stat2: 20,stat3: 30,},
               {name: "b",stat1: 30,stat2: 20,stat3: 10,},
               {name: "c",stat1: 15,stat2: 25,stat3: 50,}];

    function piechart(data){

        var currentPie = 0; //Initialize to stat1

        var fillScale = d3.scaleOrdinal(d3.schemeCategory10);
        var pieChart = d3.pie().sort(null);
        var newArc = d3.arc().innerRadius(50).outerRadius(100);              

        // Create each pie chart 
        pieChart.value(d => d.stat1);
        var stat1Pie = pieChart(data);

        pieChart.value(d => d.stat2);
        var stat2Pie = pieChart(data);

        pieChart.value(d => d.stat3);
        var stat3Pie = pieChart(data);

        // Embed slices on each name
        data.forEach( (d,i) => {
            var slices = [stat1Pie[i], stat2Pie[i], stat3Pie[i]];
            d.slices = slices;
        });

        d3.select("svg")
            .append("g")
            .attr("transform", "translate(250, 250)")
            .selectAll("path")
            .data(data)
            .enter()
            .append("path")
            .attr("d", d => newArc(d.slices[currentPie]))
            .attr("fill", (d,i) => fillScale(i))
            .attr("stroke", "black")
            .attr("stroke-width", "2px");

        function transPie(d) {

            var newPie = +this.id;
            console.log("Transition from pie " +currentPie+ " to pie " + newPie);

            d3.selectAll("path")
                .transition()
                .delay(500)
                .duration(1500)
                .attrTween("d", tweenPies)
                .on('end', function(){
                  currentPie = newPie;
                })

            function tweenPies(d, i) {
                console.log(i + ":start tween function \n current pie = " + currentPie + "\n new pie = "+newPie); 
                var currentAngleStart   = d.slices[currentPie].startAngle;
                var newAngleStart       = d.slices[newPie].startAngle;

                var currentAngleEnd     = d.slices[currentPie].endAngle;
                var newAngleEnd         = d.slices[newPie].endAngle;

                return t => {
                    var interpolateStartAngle = d3.interpolate(currentAngleStart, newAngleStart);
                    var interpolateEndAngle = d3.interpolate(currentAngleEnd, newAngleEnd);
                    d.startAngle = interpolateStartAngle(t);
                    d.endAngle = interpolateEndAngle(t);
                    return newArc(d);
                };
            };
        };

        d3.selectAll("button").on("click", transPie);  
    };
    piechart(obj);
    </script>
  </body>

</html>
&#13;
&#13;
&#13;