dc.js - dynamically change valueAccessor of a stacked layer in a lineChart and redraw it

▼魔方 西西 提交于 2019-12-08 00:46:27

问题


I am trying to realize a dashboard to display basic data.

I am actually completely stuck on an issue. Strangely enough, I couldn't find anything even similar to it online, so I don't have many leads on how to move forward.

I have mainly two charts:

  • a lineChart called "stackChart" that
    • displays consumption as a base layer with its valueAccessor function
    • dispalys production as a stacked layer with its value Accessor function
  • a barChart called "volumeChart" that is simply the rangeChart for the lineChart

I use radio buttons to select whether to aggregate the grouped data by sum or by average (using the same approach as this example) and then I just use:

stackChart.valueAccessor(/*function with new value (avg or sum)*/);
dc.redrawAll();

to refresh the base layer (consumption).

What I don't manage to do is to refresh the "stacked layer" by updating its valueAccessor! I can't find any way to access its valueAccessor (or, worst case, just completely remove the stacked layer and then add a new refreshed stacked layer using just ".stack(...)").

Here is the respective part of my code where the chart is built:

// Charts customization #js
        stackChart
            .renderArea(true)
            .height(350)
            .transitionDuration(1500)
            .dimension(dateDim)
            .group(powByTime, "Consumption")
            // BASE LAYER valueAccessor HERE
            .valueAccessor(function(d) { return d.value.conSum; })
            .x(d3.time.scale().domain([minDate, maxDate]))
            .xUnits(d3.time.days)
            .elasticY(true)
            .renderHorizontalGridLines(true)
            .legend(dc.legend().x(80).y(0).itemHeight(13).gap(5))
            .brushOn(false)
            // STACKED LAYER HERE
            .stack(powByTime, "Production", function(d) { return d.value.prodSum; })
            .rangeChart(volumeChart)
            .controlsUseVisibility(true)
        ;

And here is where I look for changes in the radio buttons and re-draw the layers:

// Listen for changes
d3.selectAll('#select-operation input')
    .on('click', function() {
        var aggrMode = this.value;  // fetch "avg" or "sum" from buttons
        // UPDATE BASE LAYER HERE:
        stackChart.valueAccessor(function(d) { var sel = accessors[aggrMode]['consPow']; return d.value[sel]; });
        // ???HOW TO UPDATE STACKED LAYER valueAccessor function???
        //stackChart.stack.valueAccessor(function(d) { var sel = accessors[aggrMode]['prodPow']; return d.value[sel]; });
        dc.redrawAll();
    });

If you need more details on what I am trying to do and full code you can check here.

As a reference, here is what it looks like:


回答1:


@Ryan's solution will probably work fine (and may be a better design), but here's the lowdown on the dc.js API with respect to stacking, in case you need it.

As described in this issue the group and stack API is pretty weird. It grew organically, in a backward-compatible way, so both the stacks and the value accessors on top of the stacks sort of branch out in a beautiful fractal of... well, no it's pretty messy.

But the issue also suggests the solution for your problem. Since chart.group() resets the set of stacks, just go ahead and build them all from scratch in your event handler:

    stackChart.group(powByTime, "Consumption") // this resets the stacks
        .valueAccessor(function(d) { var sel = accessors[aggrMode]['consPow']; return d.value[sel]; })
        .stack(powByTime, "Production", function(d) { var sel = accessors[aggrMode]['prodPow']; return d.value[sel]; });

Internally it's just emptying an array of layers/stacks and then populating it with some references.

This is quite efficient since dc.js doesn't store your data except where it is bound to the DOM elements. So it is the same amount of work to redraw using the old group and value accessor as it is to redraw using new ones.




回答2:


I don't really know dc.js, but it may be possible that you can't change an accessor once it's been set. Try writing a single function for your accessor that will return either the sum or the average, depending on the state of some variable that you can set.



来源:https://stackoverflow.com/questions/41700431/dc-js-dynamically-change-valueaccessor-of-a-stacked-layer-in-a-linechart-and-r

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!