D3 - 饼图

时间:2016-03-29 21:04:15

标签: javascript d3.js

我尝试了很多方法,但我无法在d3中绘制饼图,其中包含以下数据:

"something": [{
    "a":"some value",
    "b":"another value",
    .  
    .
    .
},{
    "c":"a value",
    "d":"value",
    .
    .
    .
}]

这个数据差不多是55,000行,每组有19个不同的值。 每组以“{”开头,以“}”结尾。我想要的代码应该动态地绘制饼图来读取数据。

var width = 550;
var height = 350;
var radius = 300/ 2;
var color = d3.scale.category20b();  //builtin range of colors
var svg = d3.select('#pie_chart').append('svg')
                                 .attr('width', width)
                                 .attr('height', height)
                                 .append('g')
                                 .attr('transform', 'translate(' + (width / 2) +',' + (height / 2) + ')');
var total = 0;

for(var a=0;a<Data.length;a++){
total=total+parseInt(Data[a].count); // simple logic to calculate total of data count value
console.log(total);
}
var pie_data=[];
for( var a=0;a<Data.length;a++){ // simple logic to calculate percentage data for the pie
pie_data[a]=(Data[a].count/total)*100;
}
var arc = d3.svg.arc().outerRadius(radius);
// creating arc element.
var pie = d3.layout.pie()
.value(function(d,i) { return pie_data[i]; })
.sort(null);
//Given a list of values, it will create an arc data for us
//we must explicitly specify it to access the value of each element in our data array
var path = svg.selectAll('path')
.data(pie(Data))
.enter()
.append('path')
.attr('d', arc)
.attr('fill', function(d, i) {
return Data[i].color;
});
//set the color for each slice to be chosen, from the color defined in sample_data.json
//this creates the actual SVG path using the associated data (pie) with the arc drawing function
*/

第二次尝试

//pie chart

var width = 300;
var height = 300;

  //each arc in the pie chart
  var outerRadius = width/2;
  var innerRadius = width/3;
  var arc = d3.svg.arc()
                  .innerRadius(innerRadius)
                  .outerRadius(outerRadius);

  //pie chart
  var pie = d3.layout.pie();
  //colors
  var color = d3.scale.category20();

  //Create SVG element
  var svg = d3.select("body")
              .append("svg")
              .attr("width", width)
              .attr("height", height);

//Set up groups
var arcs = svg.selectAll("g.arc")
              .data(pie(data))
              .enter()
              .append("g")
              .attr("class", "arc")
              .attr("transform", "translate(" + outerRadius + "," + outerRadius + ")");

//Draw arc paths
arcs.append("path")
    .attr("fill", function(d, i) {
      return color(i);
    })
    .attr("d", arc);

//Labels
arcs.append("text")
    .attr("transform", function(d) {
      return "translate(" + arc.centroid(d) + ")";
    })
    .attr("text-anchor", "middle")
    .text(function(d) {
      return d.value;
    });

有什么想法吗?

1 个答案:

答案 0 :(得分:4)

这是一个简单的例子。它涉及一些相对先进的d3概念,所以我试着解释一下。

首先,让我们考虑一下您的数据。 d3喜欢处理对象数组 s 。你有一个奇异的对象数组。因此,让我们进行一些数据转换。你有:

[{
  "a": 1,
  "b": 2,
  "c": 3  
}, {
  "d": 4,
  "e": 5
...

但你需要的是:

[
  [{
    "key": "a", 
    "value": 1
   }, {
    "key": "b", 
    "value": 2
   }, {
    "key": "c", 
    "value": 3
   }
  ],[{
    "key": "d", 
    "value": 4
   }
   ....
  ]
]

幸运的是,d3具有几乎内置的功能,d3.entries

var data = [{
    "a": 1,
    "b": 2,
    "c": 3
},{
    "a": 4,
    "d": 5,
    "e": 6
}];

var fixedData = data.map(function(d){
  return d3.entries(d);
});

其次,您希望制作多个饼图,其中外部数组是图表,内部数组是切片。这是使用nested selection的好地方。外部选择是每个饼图的g元素。在此选择内部是每个弧和标签的g元素:

// create a g for each pie chart
var p = svg.selectAll(".pie")
  .data(fixedData)
  .enter()
  .append("g")
  .attr("class", "pie")
  .attr("transform",function(d,i){
    return "translate(" + (width / 2) + "," + ((radius * i * 2) + radius) + ")"; //<-- place the g down the page
  });

// create an arc for each slice
var g = p.selectAll(".arc") //<-- this is a nested selection
  .data(function(d){
    return pie(d); //<-- d here is each element of the outer array
  })
  .enter().append("g")
  .attr("class", "arc");

让我们将这两个想法与一些有效的代码结合在一起:

&#13;
&#13;
<!DOCTYPE html>
<meta charset="utf-8">
<style>

.arc text {
  font: 15px sans-serif;
  text-anchor: middle;
}

.arc path {
  stroke: #fff;
}

</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>

var data = [{
    "a": 1,
    "b": 2,
    "c": 3
},{
    "a": 4,
    "d": 5,
    "e": 6
},{
    "d": 4,
    "f": 5,
    "b": 6
}];

var fixedData = data.map(function(d){
  return d3.entries(d);
});

var width = 500,
    height = 500,
    radius = (Math.min(width, height) / 2) / data.length;

var color = d3.scale.category10();

var arc = d3.svg.arc()
    .outerRadius(radius - 10)
    .innerRadius(0);
    
var labelArc = d3.svg.arc()
    .outerRadius(radius / 2)
    .innerRadius(radius / 2);

var pie = d3.layout.pie()
    .sort(null)
    .value(function(d) { return d.value; });

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

var p = svg.selectAll(".pie")
  .data(fixedData)
  .enter()
  .append("g")
  .attr("class", "pie")
  .attr("transform",function(d,i){
    return "translate(" + (width / 2) + "," + ((radius * i * 2) + radius) + ")";
  });
  
var g = p.selectAll(".arc")
  .data(function(d){
    return pie(d);
  })
  .enter().append("g")
  .attr("class", "arc");

g.append("path")
  .attr("d", arc)
  .style("fill", function(d) { return color(d.data.key); });

g.append("text")
    .attr("transform", function(d) { return "translate(" + labelArc.centroid(d) + ")"; })
    .text(function(d) { return d.data.key; });

</script>
&#13;
&#13;
&#13;