dc.js color pie chart slice color with color domain - d3.js

I've got a pie chart with the following for coloring the slices.
.colorAccessor(function (d) {
return d.value.count;
})
.colors(colorbrewer.YlGn[9])
.colorDomain([0, grpXtents[1]])
I am calculating the grpXtents using d3.extent
This works fine. How do I recalculate the extents for my color domain when I click on filter on other charts in the group?
Thanks!

You may not need to calculate it yourself. Please try this:
chart.on('preRedraw', function() {
chart.calculateColorDomain();
});
https://github.com/dc-js/dc.js/blob/develop/web/docs/api-latest.md#dc.colorMixin+calculateColorDomain
It should probably be an option on the colorMixin rather than requiring this hook.

Related

are there any way to change c3js stacked area chart opacity on mouse hover

I have a question regarding c3.js.
Currently, we are using c3js to display a stacked area chart, that is pretty fine, but our client asked us if we can change the individual area's opacity when customer is mouse hovering one area.
I could not find any solution for this, and hope to hear your suggetions.
Thanks
Try adding this after you've set up your chart -->
d3.selectAll(".c3-area")
.style ("pointer-events", "all")
.on("mouseover", function (d) { return d3.select(this).style("opacity", 0.6)})
.on("mouseout", function (d) { return d3.select(this).style("opacity", 0.2)})
;
The pointer-events setting is the important bit as by default most of the elements in the c3 chart are styled to ignore them.
Add it to the end of the c3 example to see it working --> https://c3js.org/samples/chart_area.html

d3 stacked area tooltip

I have this stacked area chart and I am trying to get the correct value, but have no real idea how.
I was trying to place a transparent rectangle over the chart, but then realized that I still have no idea, how to get the values.
.on("mousemove", function(d) {
tooltip
.style("display", "inline-block")
.html(d[0][1]);
})
This will give me only a fix value.
Here is my plunker
Maybe you guys have an idea.
If you inspect the data object (d), though it is array-like, you can see it also has key and index properties, and that should lead you to the right data.
.on("mousemove", function(d) {
tooltip
.style("display", "inline-block")
.html(d[d.index].data[d.key]);
})
The key is determined by the key accessor stack.keys(...) that you have defined in your plunker.
Also see the docs for the stack generator: https://github.com/d3/d3-shape/blob/master/README.md#stacks

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

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:
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.
#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.

D3 stacked area with brushing - only first nested element shows

I have an odd problem that I can't seem to figure out. I have a stacked area chart with a smaller context chart below where I can brush similar to this: http://bl.ocks.org/mbostock/1667367
The brush is working, but only for the first layer (I have left the clipping off as it is easier to see what is happening).
If I check the data in the console the brush function does only have that first key and if I change the order of the data the key in the chart changes so it is always whatever the first key happens to be.
Here is a JSFiddle: http://jsfiddle.net/goodspeedj/7Qzt4/
Here is the brushed function - the 3rd line in the function has the console.log statement showing the data only has the 'ABORTED' key (first layer).
function brushed() {
main_x.domain(brush.empty() ? mini_x.domain() : brush.extent());
//main.select(".layer").attr("d", main_area);
main.select(".layer").attr("d", function(d) { console.log(d); return main_area(d.values); })
main.select(".x.axis").call(main_xAxis);
}
I'm guessing this is something really simple - I just can't seem to see it. Thanks!
I figured this out. I should have been calling selectAll instead of select in the brushed function.
This:
main.selectAll(".layer").attr("d", function(d) { console.log(d); return main_area(d.values); })
Instead of this:
main.select(".layer").attr("d", function(d) { console.log(d); return main_area(d.values); })

How to remove NVD3 chart resize/update delay

I've created an NVD3 multiBarChart and placed it in a jQuery resizable container. When resizing the chart, each render incurs the same delay as when the chart is first drawn: staggered left-to-right delayed drawing of the bars. This looks cool when the chart is first drawn, but it's a nuisance when resizing the chart. I've experimented with nv.d3.css, reducing every delay to 0ms to no avail. Haven't yet inspected the NVD3 JS and am hoping not to need to.
Fiddle:
http://jsfiddle.net/a5Fnj/10/
var container = $("#mycontainer");
$(container[0]).resizable();
var svg = d3.select(container[0]).append("svg");
nv.addGraph(function () {
var chart = nv.models.multiBarChart();
chart.xAxis.tickFormat(d3.format(',f'));
chart.yAxis.tickFormat(d3.format(',.1f'));
d3.select(container[0]).select("svg")
.datum(exampleData())
.transition().duration(0).call(chart);
nv.utils.windowResize(chart.update);
this.stackedbar = chart;
});
function exampleData() {
return stream_layers(3, 10 + Math.random() * 100, .1).map(function (data, i) {
return {
key: 'Stream' + i,
values: data
};
});
}
As of NVD3 1.7.1 you can use the duration option:
chart.duration(0);
I used transitionDuration: -1 that worked for a stackedAreaChart.
Edit
This helped remove the transition when appending chart data, not the re-size issue, please check the comments below.
In the latest version (from github), you can set .transitionDuration():
chart.transitionDuration(0);
Edit: Even with this, some of the transitions/durations are hardcoded in the NVD3 source. The only way to get rid of those is to modify the source.

Resources