如何在 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.

结果,已排序和唯一化:

New fiddle.