Pie chart not updating properly when using brush in series chart

Podvalnyi Mikhail

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

Gordon

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.

edited at
0

Comments

0 comments
Login to comment

Related

TOP Ranking

HotTag

Archive