如何在d3.js中绘制具有自定义颜色的饼图

时间:2018-07-15 13:04:32

标签: d3.js

我得到一些0到100范围内的数据,所以我想将它们分为不同的组,例如[0、50、80、100],并为每组数据绘制不同颜色的饼图,例如< br /> (0-50红色,51-80黄色,81-100绿色)。

function drawPieChart(data) {
        var height = 500;
        var width = 500;
        var radius = Math.min(width, height)/4;
        var canvas = d3.select('#divId').append('svg')
            .attr('width', width).attr('height', height);
        var arc = d3.arc().outerRadius(radius - 10).innerRadius(0);
        var pie = d3.pie().sort(null).value(function (data) {
            return data.value;
        });
        var color = d3.scaleOrdinal().domain([0,50,80,100]).range(['red', 'orange', 'green']);
        var arcs = canvas.selectAll('arc')
            .data(pie(data))
            .enter()
            .append('g')
            .attr('class', 'arc')
            .append('path')
            .attr('d', arc).attr('transform', 'translate(' + height /4 + ',' + width /4 +')')

             .style('fill', function (data) {
                //**my silly attempt to achieve this. unsuccessful though**

                /*if(data.value > 90){
                    return arc.apply('fill', 'blue');
                }else if(data.value > 70 && data.value <= 90){
                    return arc.apply('fill', 'green');
                }else if(data.value > 50 && data.value <= 70){
                    return arc.apply('fill', 'yellow');
                }else{
                    return arc.attr('fill', 'red');
                }*/

                return color(data); // this function is resulting the whole graph of one color, whichever defind first in range (here red)
            })
    }

2 个答案:

答案 0 :(得分:1)

您可以在这里使用d3.scaleThreshold,文档:https://github.com/d3/d3-scale#threshold-scales

我使用了here中的饼图示例bl.ock来获得此密码笔:https://codepen.io/anon/pen/Yjwryz?editors=0011,这是您感兴趣的代码:

var threshold = 0.00000000000001;
var groupDomain = [
  50 + threshold,   // Red group        x: (x <= 50)
  70 + threshold,   // Yellow group     x: (50 < x <= 70)
  90 + threshold,   // Green group      x: (70 < x <= 90)
  100               // Blue group       x: (x > 90)
];
var color = d3.scaleThreshold()
              .domain(groupDomain)
              .range(['red', 'yellow', 'green', 'blue']);
                          ...
                          ...
  .style("fill", function(d) {return color(d.data); });

请注意,我为想要的组域添加了一个小的错误阈值,因为我认为.scaleThreshold已设置为可以工作直到该域中的值,即<50 not <=50。我不确定没有检查文档。

编辑: 使用“ .sort”对数据数组进行排序将解决无序数据的问题:

var data = [
  100, 20, 30, 40, 50, // Red group
  55, 10, 65, 70,     // Yellow group
  75, 80, 90,         // Green group
  95, 100             // Blue group
].sort(function (a, b) { 
  return a - b
});

更新的代码笔:https://codepen.io/anon/pen/Yjwryz?editors=0011

第二次修改: 我尝试通过在指定范围内对所有数据进行分组,然后将弧段基于落入每个指定范围内的数据点数量,来尝试您在注释中所指的内容。这是一个codepen:https://codepen.io/anon/pen/wxMNgg?editors=0010

此更改的相关代码:

var color = d3.scaleThreshold()
              .domain(groupDomain)
              .range(['red', 'yellow', 'green', 'blue']);

var groupedData = [];
data.forEach(function (e) {
  var group = color.invertExtent(color(e))[1];
      group = (group == 100) ? group : group - threshold;
  var groupIndex = groupedData.findIndex(d => d.group == group)

  if (groupIndex != -1) {
    groupedData[groupIndex].count += 1;
  } else {
    groupedData.push({
      group : group,
      count : 1
    });
  }
});

答案 1 :(得分:0)

创建饼图之前,您需要对数据进行分组

var dataByGroup = d3.nest()
  .key(function(d) { if (d<=50) return "50"; if (d<=80) return "80"; return "100"; })
  .rollup(function(v) { return v.length; })
  .entries(data);