使用d3js在半圆形圆环图中从右到左绘制进度路径

时间:2017-10-10 12:20:24

标签: javascript d3.js

我想创建一个显示完成百分比的半圆形圆环图。但要求是从右到左绘制百分比映射,而不是从左到右。以下是我的代码,

var percent = 30;        


    var ratio=percent/100;

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

    var w=300,h=300;

    var outerRadius=(w/2)-10;
    var innerRadius=85;


    var color = ['#ececec','#f06b3e','#888888'];

    var colorOld='#F00';
    var colorNew='#0F0';

    var arc=d3.svg.arc()
            .innerRadius(innerRadius)
            .outerRadius(outerRadius)
            .startAngle(0)
            .endAngle(Math.PI);


    var arcLine=d3.svg.arc()
            .innerRadius(innerRadius)
            .outerRadius(outerRadius)
            .startAngle(0);

    var svg=d3.select("#chart")
            .append("svg")
            .attr({
                width:w,
                height:h,
                class:'shadow'
            }).append('g')
            .attr({
                transform:'translate('+w/2+','+h/2+')'
            });



    var path=svg.append('path')
            .attr({
                d:arc,
                transform:'rotate(-90)'
            }).attr({
                'stroke-width':"1",
                stroke:"#666666"
            })
            .style({
                fill:color[0]
            });


    var pathForeground=svg.append('path')
            .datum({endAngle:0})
            .attr({
                d:arcLine,
                transform:'rotate(-90)'
            })
            .style({
                fill: function (d,i) {
                    return color[1];
                }
            });


    var middleCount=svg.append('text')
            .datum(0)
            .text(function(d){
                return d;
            })
            .attr({
                class:'middleText',
                'text-anchor':'middle',
                dy:0,
                dx:5
            })
            .style({
                fill:d3.rgb('#000000'),
                'font-size':'60px'



            });

    var oldValue=0;
    var arcTween=function(transition, newValue,oldValue) {
        transition.attrTween("d", function (d) {
            var interpolate = d3.interpolate(d.endAngle, ((Math.PI))*(newValue/100));

            var interpolateCount = d3.interpolate(oldValue, newValue);

            return function (t) {
                d.endAngle = interpolate(t);
                middleCount.text(Math.floor(interpolateCount(t))+'%');
                arcLine=d3.svg.arc()
            .innerRadius(innerRadius)
            .outerRadius(outerRadius)
            .startAngle(function(){
                return (newValue * (Math.PI / 180));
            });
            return arcLine(d);
            };
        });
    };


pathForeground.transition()
        .duration(0)
        .ease('cubic')
        .call(arcTween,percent,oldValue);

在上面的代码中,我们使用svg:path绘制一个半圆形圆环图,然后再次绘制另一个svg:path,用于指示从左到右的完成百分比。

我们如何使用d3js从右到左而不是从左到右绘制百分比指标?

1 个答案:

答案 0 :(得分:1)

首先,你的弧线上有一个rotate(90),这让我的大脑骨折了,所以我将它移除了。现在让我们开始思考角度的位置。从本质上讲,你想要从Math.PI/2开始制作动画并向后移向0.然后数学看起来像这样:

enter image description here

这是一些正在运行的代码:

<!DOCTYPE html>
<html>

<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.js"></script>
</head>

<body>
  Click Chart to Re-Animate!
  <div id="chart"></div>
  <script>
    var percent = Math.random() * 100;

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

    var w = 300,
      h = 300;

    var outerRadius = (w / 2) - 10;
    var innerRadius = 85;


    var color = ['#ececec', '#f06b3e', '#888888'];

    var colorOld = '#F00';
    var colorNew = '#0F0';

    var arc = d3.svg.arc()
      .innerRadius(innerRadius)
      .outerRadius(outerRadius)
      .startAngle(0)
      .endAngle(Math.PI);


    var arcLine = d3.svg.arc()
      .innerRadius(innerRadius)
      .outerRadius(outerRadius);

    var svg = d3.select("#chart")
      .append("svg")
      .attr({
        width: w,
        height: h,
        class: 'shadow'
      }).append('g')
      .attr({
        transform: 'translate(' + w / 2 + ',' + h / 2 + ')'
      })
      .on('click', function(){
        pathForeground.transition()
          .duration(1000)
          .ease('cubic')
          .call(arcTween, Math.random() * 100, 0);
      });

    var path = svg.append('path')
      .attr({
        d: arc,
        transform: 'rotate(-90)'
      }).attr({
        'stroke-width': "1",
        stroke: "#666666"
      })
      .style({
        fill: color[0]
      });

    var pathForeground = svg.append('path')
      .datum({
        endAngle: 0
      })
      .style({
        fill: function(d, i) {
          return color[1];
        }
      });

    var middleCount = svg.append('text')
      .datum(0)
      .text(function(d) {
        return d;
      })
      .attr({
        class: 'middleText',
        'text-anchor': 'middle',
        dy: 0,
        dx: 5
      })
      .style({
        fill: d3.rgb('#000000'),
        'font-size': '60px'
      });

    var oldValue = 0;
    
    var arcTween = function(transition, newValue, oldValue) {
      transition.attrTween("d", function(d) {

        arcLine.startAngle(Math.PI / 2);
        
        var interpolate = d3.interpolate(Math.PI / 2, (Math.PI / 2) - (Math.PI * (newValue / 100)));
        var interpolateCount = d3.interpolate(oldValue, newValue);

        return function(t) {
          d.endAngle = interpolate(t);
          middleCount.text(Math.floor(interpolateCount(t)) + '%');
          return arcLine(d);
        };
      });
    };

    pathForeground.transition()
      .duration(1000)
      .ease('cubic')
      .call(arcTween, percent, oldValue);
  </script>
</body>

</html>