Custom legend based on color of bars in a dc.js composite chart

前端 未结 1 1486
半阙折子戏
半阙折子戏 2021-01-16 12:16

I implemented a composite chart with two bar charts in which one bar chart consists of bars with different colored bars. Now, I want to create a custom legend that represen

相关标签:
1条回答
  • 2021-01-16 12:24

    Let me provide a little bit of background about how the legend is built.

    The legend in dc.js is really not all that sophisticated. It just calls .legendables() on the chart, and the chart decides what items to display in the legend.

    Each chart has its own special-purpose code for this.

    If we look at the source for compositeChart.legendables(), it's just recursively getting the legendables for each child chart and concatenating them:

    _chart.legendables = function () {
        return _children.reduce(function (items, child) {
            if (_shareColors) {
                child.colors(_chart.colors());
            }
            items.push.apply(items, child.legendables());
            return items;
        }, []);
    };
    

    The pie chart creates a legendable for each pie slice:

    _chart.legendables = function () {
        return _chart.data().map(function (d, i) {
            var legendable = {name: d.key, data: d.value, others: d.others, chart: _chart};
            legendable.color = _chart.getColor(d, i);
            return legendable;
        });
    };
    

    The legendables for the bar chart come from the stack mixin, which creates a legendable for each stack:

    _chart.legendables = function () {
        return _stack.map(function (layer, i) {
            return {
                chart: _chart,
                name: layer.name,
                hidden: layer.hidden || false,
                color: _chart.getColor.call(layer, layer.values, i)
            };
        });
    };
    

    Given that there's currently no way to get a bar chart to display a pie chart's legend, I think the easiest thing to do is override legendables for your bar chart with its custom colors:

    buttonPress.legendables = function() {
        return btnGroup.all().map(function(kv) {
            return {
                chart: buttonPress,
                // display the value as the text (not sure what you want here)
                name: kv.value,
                // apply the chart's color scale to get the color
                color: buttonPress.colors()(kv.value)
            };
        })
    };
    

    There are probably some more details to be worked out, such as what if the same value occurs twice? I am assuming you can just read the input data from the group and .map() it, but you might need to generate your data a different way.

    But this should give the general idea. Lmk if it doesn't work and I'll be glad to follow up.

    0 讨论(0)
提交回复
热议问题