2017-10-10 653 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>