来自JSON的D3.JS Grouped Donut Chart

时间:2013-07-08 04:22:48

标签: javascript html css svg d3.js

所以,我手上有the following JSON data,我需要找到在D3中绘制圆环图的最佳方法。忽略“信息”和“政治家”阵列并且现在严格关注“行业”阵列,我想实现以下图表:

Pardon the 2-minute Photoshop...

请原谅2分钟的Photoshop工作......

基本上每条小黑线代表一个行业。每个行业都受到民主党人,共和党人和独立人士的影响。我想创建一个圆环图(或两个圆环图),按照上面的方式划分为yas和nays。

我已尝试对此进行编码,我仍然了解D3,所以请耐心等待。该代码看起来像这样:

d3.json('mock2.json', function(errors, data) {
//Formatting of data
var yeas = [];
var nays = [];

for(var i = 0; i < data.industries.length; i++) {
    var yea_temp = {};
    var nay_temp = {};
    var yea_c = data.industries[i].yea_contribution;
    var nay_c = data.industries[i].nay_contribution;

    yea_temp.name = data.industries[i].name;
    yea_temp.influence = {"D": yea_c.d_influence, "R": yea_c.r_influence, "I": yea_c.i_influence};

    nay_temp.name = data.industries[i].name;
    nay_temp.influence = {"D": nay_c.d_influence, "R": nay_c.r_influence, "I": nay_c.i_influence};

    yeas.push(yea_temp);
    nays.push(nay_temp);
}

//Log the variables for console inspection
console.log(yeas);
console.log(nays);

//Declare variables
var width = 800,
    height = 600,
    radius = Math.min(width, height)/2;

var svg = d3.select('#graph').append('svg')
    .attr('width', width)
    .attr('height', height);

var group = svg.append('g')
    .attr('transform', 'translate(300, 300)');

var arc = d3.svg.arc()
    .innerRadius(200)
    .outerRadius(radius);

var yea_pie = d3.layout.pie()
    .value(function(d, i) {
        if(i == 0)
            return d.influence.D;
        else if(i == 1)
            return d.influence.I;
        else
            return d.influence.R;
    })
    .startAngle(-Math.PI/2)
    .endAngle(Math.PI/2);

var color = d3.scale.ordinal()
    .range(['rgba(92,188,239,0.5)', 'rgba(255,76,76,0.5)', 'rgba(150,163,170,0.5)']);

var yea_arcs = group.selectAll('.arc')
    .data(yea_pie(yeas))
    .enter()
    .append('g')
    .attr('class', 'arc')
    .attr('class', function(d) { console.log(d); });

yea_arcs.append('path')
    .attr('d', arc)
    .attr('fill', function(d) { return color(d.data); });

到目前为止,我只是将屏幕呈现为蓝色半圆形,但它被分为三条路径,所以至少我知道我正在循环。如何根据影响对这些部分进行细分(缺少更好的词)?

你会在我的代码的第一部分注意到,我基本上采用了我已经给出的JSON并尝试将其格式化得更好,因此在D3中更容易。这是最佳做法吗?我觉得D3中可能有一些神奇的功能让我所有的烦恼消失了,但我不知道。大多数情况下,我只是寻求一点指导(但代码肯定会很好!),所以我会采取我能得到的。

另外,here's a fiddle to play with如果您愿意这样做。

1 个答案:

答案 0 :(得分:2)

我已经找到了在D3中进行叠加饼图的方法。我不完全确定这是否是“正确的”惯例,但它肯定运作良好。 Here's a fiddle跟随。{/ p>

我重组了我的yeasnays数组,在一个对象中指定第一级数据值(这样D3可以正确循环),然后还包括聚会和名称。以下是yeas数组的外观示例:

Yeas Array

基本上有两个数组yeasnays,每个数组都有9个具有值valuepartyname的对象。通过这种方式,我可以传递d3.layout.pie任一数组的数据,并在该饼图布局value中提供d.value。更简单地说,这是解释的代码片段:

var yea_pie = d3.layout.pie()
    .sort(null)
    .value(function(d) { return d.value; })  //This computes a pie value for each yeas.value (d.value)
    .startAngle(-Math.PI/2)
    .endAngle(Math.PI/2);

var yeas_industry = yea_group.selectAll('.arc')
    .data(yea_pie(yeas))  //Pass the yeas variable to yea_pie
    .enter().append('g')
    .attr('class', 'arc'); 

这是我见过的唯一一个用于堆积饼图的解决方案。话虽如此,我会认为这是正确的,但如果其他任何人想到更好的方式,我会很有兴趣知道。