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

D3.js 如何在dc.js中按堆栈过滤堆叠折线图?,d3.js,dc.js,crossfilter,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

我正在为仪表板制作堆叠折线图:

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();


到目前为止,它运行良好,但我遇到了一个障碍。我需要实现一个选项来按单个堆栈过滤图表。这在dc.js中可能吗?如果有必要,我可以修改和重写整个代码,如果需要,还可以要求我的客户以不同的方式重新构建数据。数据中还有其他字段,我可以过滤其他图表,因此保留这些功能非常重要。

根据设计,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()
,与您的实际用例不匹配,您可能需要自定义该接口,但它在此处有效

这把小提琴的叉子演示了以下功能:

我还添加了一个饼图来说明正在发生的事情。通过执行以下操作,可以通过饼图对图例进行筛选

  catPie.filter(d.name);
而不是

  categories.filter(d.name);
这样,您可以在饼图的切片中看到结果过滤器。您还可以获得切换行为,即可以再次单击返回空选择,然后单击多个类别。如果需要切换行为,请留下注释,我尝试想出一种不使用饼图的方法来添加它


有时,图例似乎应该是自己的独立图表类型…

您的意思是,隐藏和显示堆栈,还是选择一个堆栈,并按堆栈表示的值过滤所有其他图表?理想情况下,客户会同时选择这两种类型。通过实现具有相同维度和值的二级饼图,我成功地创建了一个临时解决方案,该饼图为我提供了必要的功能。我仍然认为如果我能用一张图表来管理它会更好。是否可以添加用于单击图例的筛选器处理程序?