如何在只有一个图例的同时向多个饼图添加标题? [英] How to add titles to multiple pie charts, while having a single legend?

查看:56
本文介绍了如何在只有一个图例的同时向多个饼图添加标题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下数据:

var data = [
  [
    {"piece_value":76.34,name:"AG",group:"G1"},
    {"piece_value":69.05,name:"A3",group:"G1"},
    {"piece_value":275.19,name:"A4",group:"G1"}
  ],
  [
    {"piece_value":69.93,name:"AG",group:"G2"},
    {"piece_value":61.50,name:"A3",group:"G2"},
    {"piece_value":153.31,name:"A4",group:"G2"}
  ],
  [
    {"piece_value":67.48,name:"AG",group:"G3"},
    {"piece_value":58.03,name:"A3",group:"G3"},
    {"piece_value":145.93,name:"A4",group:"G3"}
  ]
];

,我有3个饼图(请参见代码段).我想将相应的group值放在每个饼图的顶部,然后将图例移到右侧(垂直图例).问题是现在我有3个图例(每个饼图一个),但实际上它始终是相同的图例.因此,我不想将其复制3次,而是要在右侧放置一个图例,同时将group值用作标题. 该怎么做?

and I have 3 pie charts (see the code snippet). I want to put the corresponding group values on top of each pie chart, and move a legend to the right side (a vertical legend). The problem is that now I have 3 legends (one per pie chart), but in fact it's always the same legend. Therefore instead of duplicating it 3 times, I want to have a single legend on the right side, while putting group values as titles. How to do this?

var data = [
  [
    {"piece_value":76.34,name:"AG",group:"G1"},
    {"piece_value":69.05,name:"A3",group:"G1"},
    {"piece_value":275.19,name:"A4",group:"G1"}
  ],
  [
    {"piece_value":69.93,name:"AG",group:"G2"},
    {"piece_value":61.50,name:"A3",group:"G2"},
    {"piece_value":153.31,name:"A4",group:"G2"}
  ],
  [
    {"piece_value":67.48,name:"AG",group:"G3"},
    {"piece_value":58.03,name:"A3",group:"G3"},
    {"piece_value":145.93,name:"A4",group:"G3"}
  ]
];

var m = 10,
    r = 90,
    z = d3.scale.category20c();

var svg = d3.select("body").selectAll("svg")
    .data(data)
    .enter().append("svg")
    .attr("width", (r + m) * 2)
    .attr("height", (r + m) * 2)
    .append("g")
    .attr("transform", "translate(" + (r + m) + "," + (r + m) + ")");

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

var arc = d3.svg.arc()
    .innerRadius(r / 2.2)
    .outerRadius(r/1.2)

svg.selectAll("path")
    .data(pie)
    .enter().append("path")
    .attr("d", arc)
    .style("fill", function(d, i) {
        return z(i);
    });

svg.selectAll("foo")
    .data(pie)
    .enter()
    .append("text")
    .attr("text-anchor", "middle")
    .attr("transform", d => "translate(" + arc.centroid(d) + ")")
    .text(d => d.data.piece_value);
		
svg.selectAll("foo")
    .data(d=>d)
    .enter()
    .append("text")
		.attr("transform", (d,i)=>"translate(" + (-r + 2.5*m + (i * 70)) + "," +  (-r + m) + ")")
		.text(d=>d.name);
		
svg.selectAll("foo")
    .data(d=>d)
    .enter()
    .append("rect")
		.attr("transform", (d,i)=>"translate(" + (-r + m + (i * 70)) + "," +  (-r) + ")")
		.attr("width", 10)
		.attr("height", 10)
		.style("fill", (d, i) => z(i));

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

推荐答案

每个甜甜圈都有一个图例的想法是,它允许具有不同的数据(关于分类变量).但是,由于您说过只想要一个图例,所以我假设每个图表的分类变量都相同.既然如此,我们可以创建一个新的数据数组...

The idea behind of having one legend for each donut is that it allows having different data (regarding the categorical variables). However, since you said you want only one legend, I'm assuming that the categorical variables are the same for each chart. That being the case, we can create a new data array...

var legendData = data[0].map(d=>d.name);

...使用任何索引(同样,由于数组是相同的,所以重新分配了类别变量),并且我们无需绘制另一个SVG,而可以简单地使用HTML创建图例:

... using any index (since, again, the arrays are the same regading the categorical variable), and instead of drawing another SVG, we can simply create the legend with HTML:

var legendDiv = d3.select("#legend");

var legendRow = legendDiv.selectAll("foo")
    .data(legendData)
    .enter()
    .append("div")
    .style("margin-bottom", "2px");

legendRow.append("div")
    .html("&nbsp")
    .attr("class", "rect")
    .style("background-color", (d, i) => z(i));

legendRow.append("div")
    .html(d => d);

以下是带有垂直图例的演示:

Here is a demo with the vertical legend:

var data = [
  [
    {"piece_value":76.34,name:"AG",group:"G1"},
    {"piece_value":69.05,name:"A3",group:"G1"},
    {"piece_value":275.19,name:"A4",group:"G1"}
  ],
  [
    {"piece_value":69.93,name:"AG",group:"G2"},
    {"piece_value":61.50,name:"A3",group:"G2"},
    {"piece_value":153.31,name:"A4",group:"G2"}
  ],
  [
    {"piece_value":67.48,name:"AG",group:"G3"},
    {"piece_value":58.03,name:"A3",group:"G3"},
    {"piece_value":145.93,name:"A4",group:"G3"}
  ]
];

var m = 10,
    r = 90,
    z = d3.scale.category20c();

var svg = d3.select("body").selectAll("svg")
    .data(data)
    .enter().append("svg")
    .attr("width", (r + m) * 2)
    .attr("height", (r + m) * 2)
    .append("g")
    .attr("transform", "translate(" + (r + m) + "," + (r + m) + ")");

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

var arc = d3.svg.arc()
    .innerRadius(r / 2)
    .outerRadius(r/1)

svg.selectAll("path")
    .data(pie)
    .enter().append("path")
    .attr("d", arc)
    .style("fill", function(d, i) {
        return z(i);
    });

svg.selectAll("foo")
    .data(pie)
    .enter()
    .append("text")
    .attr("text-anchor", "middle")
    .attr("transform", d => "translate(" + arc.centroid(d) + ")")
    .text(d => d.data.piece_value);
		
var legendData = data[0].map(d=>d.name);

var legendDiv = d3.select("#legend");

var legendRow = legendDiv.selectAll("foo")
	  .data(legendData)
    .enter()
    .append("div")
		.style("margin-bottom", "2px");

legendRow.append("div")
		.html("&nbsp")
		.attr("class", "rect")
		.style("background-color", (d, i) => z(i));
		
legendRow.append("div")
		.html(d=>d);
		

.rect {
	width: 20px;
	float: left;
	margin-right: 10px;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="legend">Legend:</div>

PS :您说过想要在右侧显示图例.为此,只需并排创建2个div:在左边添加SVG,在右边添加图例.我会把这留给你做作业.

PS: you said that you want the legend at the right hand side. To do that, simply create 2 divs, side by side: on the left one you append the SVGs, and on the right one you append the legend. I'll leave this as a homework for you.

PS2 :请注意scale.category20以先到先得的方式工作的事实.因此,为了使图例准确,内部数组中分类变量的顺序必须相同.

PS2: pay attention to the fact that scale.category20 works on a first-come, first-served basis. So, for the legends to be accurate, the order of the categorical variables in the inner arrays has to be the same.

这篇关于如何在只有一个图例的同时向多个饼图添加标题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆