2017-10-10 650 views
0

我想创建一个显示完成百分比的半圆环图。但要求是从右向左绘制百分比映射,而不是从左向右绘制。下面是我的代码,使用d3js在半圆环形图中绘制从右到左的进度路径

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画一个半圆圆环图:路径,然后再绘制另一个SVG:路径指示从左至右完成的百分比。

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

+0

你肯定这就是你现在想要的吗?因为当我向你的转换添加一个不是0的持续时间时,动画非常古怪。 https://jsfiddle.net/nph/qn5x9vp0/ –

+0

@NathanHinchey我的意图是根据百分比值将从半圈右端的进度绘制到左侧,但没有奏效。我调整arcTween中arcLine对象的startAngle()从0到newValue *(Math.PI/180),这就是为什么它像这样执行。如果我再次将此值更改为0,代码将起作用。我需要180度的startAngle和左侧的情节。例如,如果我需要绘制的百分比值为30,则应该从半圆的180度开始向左绘制30%。 –

回答

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>