I have 1 pie chart and 1 series line chart with brush. Currently when I brushing the pie chart updates, but shows the same result regardless of the selected range. How to make brush work correctly?
const pieChart = dc.pieChart('#piechart');
const chart = dc.seriesChart('#chart');
const groupParameter = 'markdown';
const data = d3.csvParse(d3.select('pre#data').text());
data.forEach(d => {
d.week = +d.week;
d.markdown = +d.markdown;
});
const ndx = crossfilter(data);
const pieDimension = ndx.dimension(d => d.itemCategory);
const dimension = ndx.dimension(d => [d.itemCategory, d.week]);
const pieGroup = pieDimension.group().reduceSum(d => d[groupParameter]);
const group = dimension.group().reduceSum(d => d[groupParameter]);
pieChart
.width(768)
.height(480)
.dimension(pieDimension)
.group(pieGroup)
.legend(dc.legend());
chart
.width(768)
.height(480)
.chart(c => dc.lineChart(c).curve(d3.curveCardinal))
.x(d3.scaleLinear().domain([27, 38]))
.brushOn(true)
.yAxisLabel(groupParameter)
.yAxisPadding('5%')
.xAxisLabel('Week')
.elasticY(true)
.dimension(dimension)
.group(group)
.mouseZoomable(true)
.seriesAccessor(d => d.key[0])
.keyAccessor(d => d.key[1])
.valueAccessor(d => d.value)
.legend(
dc
.legend()
.itemHeight(13)
.gap(5)
.horizontal(1)
.legendWidth(140)
.itemWidth(70)
);
chart.margins().left += 100;
dc.renderAll();
https://jsfiddle.net/qwertypomy/L37d01e5/#&togetherjs=HF15j0M5pH
It doesn't look like brushing was ever properly implemented for series charts.
The issue is that the dimension key for series chart is a 2-dimensional array, but a normal RangedFilter is applied, which doesn't understand these keys.
You can manually apply a filter handler which looks at the right part of the key:
chart.filterHandler(function(dimensions, filters) {
if (filters.length === 0) {
dimension.filter(null);
} else {
var filter = dc.filters.RangedFilter(filters[0][0], filters[0][1]);
dimension.filterFunction(function(k) {
return filter.isFiltered(k[1]);
});
}
return filters;
});
Actually, I'm not sure if there is an elegant way to fix this. I've started an issue to track it: https://github.com/dc-js/dc.js/issues/1471
EDIT: This doesn't work unless it's applied to both the series chart and all of its children. Horribly inefficient, but like so:
function filterHandler(dimensions, filters) {
if (filters.length === 0) {
dimension.filter(null);
} else {
var filter = dc.filters.RangedFilter(filters[0][0], filters[0][1]);
dimension.filterFunction(function(k) {
return filter.isFiltered(k[1]);
});
console.log('all',all.value());
}
return filters;
}
chart
.chart(c => dc.lineChart(c).curve(d3.curveCardinal).filterHandler(filterHandler))
.filterHandler(filterHandler);
New version of fiddle, with dataCount
to show it's working now: https://jsfiddle.net/gordonwoodhull/qga6z1yu/39/
We really need a generalized version of https://github.com/dc-js/dc.js/pull/682 to apply filters only once, in a cooperative way between multiple charts which share the same dimension.
Right now, this will apply the filter four times every time the brush changes!
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments