如何在 dc.js 中为不同颜色的条形图添加图例?
How to add legend for a bar chart with different colors in dc.js?
下面是带有彩色条的条形图的代码片段:
var Dim2 = ndx.dimension(function(d){return [d.SNo, d.something ]});
var Group2 = Dim2.group().reduceSum(function(d){ return d.someId; });
var someColors = d3.scale.ordinal().domain(["a1","a2","a3","a4","a5","a6","a7","a8"])
.range(["#2980B9","#00FFFF","#008000","#FFC300","#FF5733","#D1AEF1","#C0C0C0","#000000"]);
barChart2
.height(250)
.width(1000)
.brushOn(false)
.mouseZoomable(true)
.x(d3.scale.linear().domain([600,800]))
.elasticY(false)
.dimension(Dim2)
.group(Group2)
.keyAccessor(function(d){ return d.key[0]; })
.valueAccessor(function(d){return d.value; })
.colors(someColors)
.colorAccessor(function(d){return d.key[1]; });
如何在此图表中添加图例?
在 crossfilter 中使用复合键真的很棘手,除非你真的需要,否则我不推荐它。
Crossfilter 只理解标量,因此即使您可以生成作为数组的维度和组键并正确检索它们,crossfilter 会将这些数组强制转换为字符串,这可能会导致麻烦。
在这里,发生的事情是 Group2.all()
按字符串顺序遍历您的数据,因此您按
的顺序获取键
[1, "a1"], [10, "a3"], [11, "a4"], [12, "a5"], [2, "a3"], ...
在不改变数据形状的情况下,一种解决方法是在 legendables
函数中对数据进行排序:
barChart2.legendables = function() {
return Group2.all().sort((a,b) => a.key[0] - b.key[0])
.map(function(kv) {
return {
chart: barChart2,
name: kv.key[1],
color: barChart2.colors()(kv.key[1]) }; }) };
一个不相关的问题是 dc.js 非常字面地采用 X 域,因此即使 [1,12]
包含所有值,最后一个柱没有显示,因为右侧恰好在 12 处结束,并且条形图在 12 和 13 之间绘制。
所以:
.x(d3.scale.linear().domain([1,13]))
现在图例与数据匹配!
Fork of your fiddle (also with dc.css).
编辑:当然,您也希望图例项目独一无二。您可以这样定义 uniq
:
function uniq(a, kf) {
var seen = [];
return a.filter(x => seen[kf(x)] ? false : (seen[kf(x)] = true));
}
向 legendables
添加一个步骤:
barChart2.legendables = function() {
var vals = uniq(Group2.all(), kv => kv.key[1]),
sorted = vals.sort((a,b) => a.key[1] > b.key[1] ? 1 : -1);
// or in X order: sorted = vals.sort((a,b) => a.key[0] - b.key[0]);
return sorted.map(function(kv) {
return {
chart: barChart2,
name: kv.key[1],
color: barChart2.colors()(kv.key[1]) }; }) };
请注意,我们按落在 key[1]
中的 d.something
的字符串值排序。如评论中所示,也可以按 x 顺序 (d.SNo
, key[0]
) 排序。我不建议按 y 排序,因为那是 reduceSum
.
结果,已排序和唯一化:
下面是带有彩色条的条形图的代码片段:
var Dim2 = ndx.dimension(function(d){return [d.SNo, d.something ]});
var Group2 = Dim2.group().reduceSum(function(d){ return d.someId; });
var someColors = d3.scale.ordinal().domain(["a1","a2","a3","a4","a5","a6","a7","a8"])
.range(["#2980B9","#00FFFF","#008000","#FFC300","#FF5733","#D1AEF1","#C0C0C0","#000000"]);
barChart2
.height(250)
.width(1000)
.brushOn(false)
.mouseZoomable(true)
.x(d3.scale.linear().domain([600,800]))
.elasticY(false)
.dimension(Dim2)
.group(Group2)
.keyAccessor(function(d){ return d.key[0]; })
.valueAccessor(function(d){return d.value; })
.colors(someColors)
.colorAccessor(function(d){return d.key[1]; });
如何在此图表中添加图例?
在 crossfilter 中使用复合键真的很棘手,除非你真的需要,否则我不推荐它。
Crossfilter 只理解标量,因此即使您可以生成作为数组的维度和组键并正确检索它们,crossfilter 会将这些数组强制转换为字符串,这可能会导致麻烦。
在这里,发生的事情是 Group2.all()
按字符串顺序遍历您的数据,因此您按
[1, "a1"], [10, "a3"], [11, "a4"], [12, "a5"], [2, "a3"], ...
在不改变数据形状的情况下,一种解决方法是在 legendables
函数中对数据进行排序:
barChart2.legendables = function() {
return Group2.all().sort((a,b) => a.key[0] - b.key[0])
.map(function(kv) {
return {
chart: barChart2,
name: kv.key[1],
color: barChart2.colors()(kv.key[1]) }; }) };
一个不相关的问题是 dc.js 非常字面地采用 X 域,因此即使 [1,12]
包含所有值,最后一个柱没有显示,因为右侧恰好在 12 处结束,并且条形图在 12 和 13 之间绘制。
所以:
.x(d3.scale.linear().domain([1,13]))
现在图例与数据匹配!
Fork of your fiddle (also with dc.css).
编辑:当然,您也希望图例项目独一无二。您可以这样定义 uniq
:
function uniq(a, kf) {
var seen = [];
return a.filter(x => seen[kf(x)] ? false : (seen[kf(x)] = true));
}
向 legendables
添加一个步骤:
barChart2.legendables = function() {
var vals = uniq(Group2.all(), kv => kv.key[1]),
sorted = vals.sort((a,b) => a.key[1] > b.key[1] ? 1 : -1);
// or in X order: sorted = vals.sort((a,b) => a.key[0] - b.key[0]);
return sorted.map(function(kv) {
return {
chart: barChart2,
name: kv.key[1],
color: barChart2.colors()(kv.key[1]) }; }) };
请注意,我们按落在 key[1]
中的 d.something
的字符串值排序。如评论中所示,也可以按 x 顺序 (d.SNo
, key[0]
) 排序。我不建议按 y 排序,因为那是 reduceSum
.
结果,已排序和唯一化: