修改D3.js圆形进度图以显示百分比范围

时间:2016-05-09 18:02:29

标签: javascript d3.js graph

我正在使用d3.js来显示圆形进度图。它工作得很好,但我想在图表上以不同的颜色显示特定的百分比范围。我想在图表上显示75% - 90%的不同颜色。我怎样才能做到这一点?我看了一下圆环图来完成这个,但我喜欢圆形图是动画的,所以我想坚持下去并修改它以满足我的需求。

目标:

在图表上以不同的线条颜色添加75%-90%的百分比范围。该图表显示75%-90%的“准确度”。

加成:

添加“75%至90%”标签,如下图所示: dynamic programming

JS:

var colors = {
    'pink': '#ffffff',
    'yellow': '#f0ff08',
    'green': '#47e495'
};

var color = colors.pink;
var line_two_color = colors.green;

var radius = 50;
var border = 3;
var padding = 10;
var startPercent = 0;
var endPercent = 0.90;


var twoPi = Math.PI * 2;
var formatPercent = d3.format('.0%');
var boxSize = 130;


var count = Math.abs((endPercent - startPercent) / 0.01);
var step = endPercent < startPercent ? -0.01 : 0.01;

var arc = d3.svg.arc()
    .startAngle(0)
    .innerRadius(radius)
    .outerRadius(radius - border);

var parent = d3.select('div#circle_graph');

var svg = parent.append('svg')
    .attr('width', boxSize)
    .attr('height', boxSize);

var defs = svg.append('defs');

var g = svg.append('g')
    .attr('transform', 'translate(' + boxSize / 2 + ',' + boxSize / 2 + ')');

var meter = g.append('g')
    .attr('class', 'progress-meter');

meter.append('path')
    .attr('class', 'background')
    .attr('fill', '#ccc')
    .attr('fill-opacity', 0.5)
    .attr('d', arc.endAngle(twoPi));

var foreground = meter.append('path')
    .attr('class', 'foreground')
    .attr('fill', color)
    .attr('fill-opacity', 1)
    .attr('stroke', color)
    .attr('stroke-width', 5)
    .attr('stroke-opacity', 1)

var front = meter.append('path')
    .attr('class', 'foreground')
    .attr('fill', color)
    .attr('fill-opacity', 1);

var numberText = meter.append('text')
    .attr('fill', '#fff')
    .attr('text-anchor', 'middle')
    .attr('dy', '.35em');

function updateProgress(progress) {
    foreground.attr('d', arc.endAngle(twoPi * progress));
    front.attr('d', arc.endAngle(twoPi * progress));
    numberText.text(formatPercent(progress));
}

var progress = startPercent;

(function loops() {
    updateProgress(progress);

    if (count > 0) {
        count--;
        progress += step;
        setTimeout(loops, 10);
    }
})();

CSS:

.progress-meter text {
    font-family:"Helvetica Neue", Helvetica, Arial, sans-serif;
    font-size: 24px;
    font-weight: bold;
}

HTML:

<div id="circle_graph"></div>

1 个答案:

答案 0 :(得分:1)

希望我能正确理解你的问题!

另请注意,如果您的数据是%(而不是弧度),则您必须添加d3.scale以将[0,100]域转换为[0,2pi]。

以下代码模拟具有两个单独弧的单个进度弧。一个用于0-75%范围,一个用于75%以上。两个弧都基于相同的数据绘制,但关键是使用最小和最大函数在数据超过75%阈值时钳制数据。

对于第一个柱,当进度超过75%时,结束角停止...

.attr('d', function(d){
    progressArc.startAngle(0)
    return progressArc.endAngle( Math.min(d,(3/2)*Math.PI) )();
  })

<强> Math.min(d,(3/2)*Math.PI)

而对于第二个柱,结束角度仅在数据通过75%后开始变化......

.attr('d', function(d){
    progressArc.startAngle((3/2)*Math.PI)
    return progressArc.endAngle( Math.max(d,(3/2)*Math.PI ))();
  })

<强> Math.max(d,(3/2)*Math.PI

最终结果看起来像一条条在通过阈值时改变颜色。

&#13;
&#13;
var height = 20,
     width = 70,
     progress = 3;

d3.select('div').append('svg')
    .attr('width','100%')
    .attr('viewBox','0 0 ' + width + ' ' + height)


d3.select('svg').append('g')
    .attr('transform','translate('+width/2+','+height/2+')')
    .attr('id','main')

var progressArc = d3.svg.arc()
        .innerRadius(7)
        .outerRadius(9)
        .startAngle(0)
        .endAngle(2*Math.PI)

var progressBar1 = d3.select('#main').append('g').attr('class','progressBar1'),
    progressBar2 = d3.select('#main').append('g').attr('class','progressBar2');

progressBar1.selectAll('path')
    .data([progress])
    .enter()
    .append('path')
    .attr('d', function(d){
        progressArc.startAngle(0)
        return progressArc.endAngle( Math.min(d,(3/2)*Math.PI) )();
      })

progressBar2.selectAll('path')
    .data([progress])
    .enter()
    .append('path')
    .attr('fill','red')
    .attr('d', function(d){
        progressArc.startAngle((3/2)*Math.PI)
        return progressArc.endAngle( Math.max(d,(3/2)*Math.PI ))();
      })

var update = function(){
  
  progress = progress >= 2*Math.PI ? 0 : progress + Math.random()*(1/200)*Math.PI;
  
  console.log(progress)
  progressBar1.selectAll('path')
    .data([progress])
    .attr('d', function(d){
        progressArc.startAngle(0)
        return progressArc.endAngle( Math.min(d,(3/2)*Math.PI) )();
      })
  
  progressBar2.selectAll('path')
    .data([progress])
    .attr('d', function(d){
        progressArc.startAngle((3/2)*Math.PI)
        return progressArc.endAngle( Math.max(d,(3/2)*Math.PI ))();
      })

}

setInterval( update, 12);
&#13;
svg{
  border: solid green 1px;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

<div></div>
&#13;
&#13;
&#13;