如何在dc.js中按堆栈过滤堆叠的折线图?

时间:2016-08-31 14:22:15

标签: d3.js dc.js crossfilter

我正在制作仪表板的叠加折线图:

var json = [...]
var timeFormat = d3.time.format.iso;
json = json.map(function(c){
    c.date = timeFormat.parse(c.date);
  return c;
});
var data = crossfilter(json);
var days = data.dimension(function (d) {
  return d.date;
});
var minDate = days.bottom(1)[0].date;
var maxDate = days.top(1)[0].date;

var lineValues = days.group().reduce(function (acc, cur) {
  acc[cur.line] = (acc[cur.line] || 0) + 1
  return acc;
}, function (acc, cur) {
  acc[cur.line] = (acc[cur.line] || 0) - 1
  return acc;
}, function () {
  return {};
});

var personChart = dc.lineChart("#graph");
personChart
  .turnOnControls(true)
  .width(600).height(350)
  .dimension(days)
  .group(lineValues, "completed")
        .valueAccessor(function (d) {
            return d.value.completed || 0;
        })
        .stack(lineValues, "assigned", function (d) {
            return d.value.assigned || 0;
        })
        .stack(lineValues, "inactive", function (d) {
            return d.value.inactive || 0;
        })
        .stack(lineValues, "active", function (d) {
            return d.value.active || 0;
        })
        .stack(lineValues, "new", function (d) {
            return d.value.new || 0;
        })
        .stack(lineValues, "temp", function (d) {
            return d.value.temp || 0;
        })
        .elasticY(true)
  .renderArea(true)
  .x(d3.time.scale().domain([minDate, maxDate]))
  .ordinalColors(colorScale)
  .legend(dc.legend().x(50).y(10).itemHeight(13).gap(5).horizontal(true));
dc.renderAll();

Fiddle here

到目前为止工作正常,但我遇到了障碍。我需要实现一个选项来按单个堆栈过滤图表。这在dc.js中是否可行?如有必要,我可以修改和重写整个代码,并在需要时让我的客户以不同方式重新编码数据。我为其他图表过滤了数据中的其他字段,因此保留该功能非常重要。

1 个答案:

答案 0 :(得分:3)

按照设计,dc.js有很多“漏洞抽象”,所以通常有办法获取你想要的数据,并通过下降到d3来自定义行为,即使它的功能不是图书馆预计。

使用饼图的解决方法非常合理,但我同意点击图例会更好。

这是一种方法:

var categories = data.dimension(function (d) {
  return d.line;
});
personChart
  .on('renderlet', function(chart) {
    chart.selectAll('.dc-legend-item')
    .on('click', function(d) {
      categories.filter(d.name);
      dc.redrawAll();
    })
  });

基本上,一旦图表完成绘图,我们就会选择图例项并替换我们自己的点击行为,它会过滤我们为此目的创建的另一个维度。

这确实依赖于与您要过滤的值匹配的图例文本。您可能必须在图例及其图表之间自定义未记录的界面.legendables(),如果这与您的实际用例不匹配,但它可以在这里工作。

这个小提琴的分支演示了功能:https://jsfiddle.net/gordonwoodhull/gqj00v27/8/

我还添加了一个饼图,只是为了说明发生了什么。您可以通过饼图通过

来设置图例过滤器
  catPie.filter(d.name);

而不是

  categories.filter(d.name);

通过这种方式,您可以在饼图切片中看到生成的过滤器。您还可以获得切换行为,即能够再次单击以返回空选择,并单击多个类别。如果需要切换行为,请发表评论,我尝试在不使用饼图的情况下添加一种方法。

有时看起来传说应该是它自己独立的图表类型......