更新刷选区域图表的y轴。

18
我正在使用d3.js,并根据这个示例修改了一个 brushed area chart。除了基于brush的变化,我希望图表的y轴也能根据数据中在brush范围内的y值重新绘制(类似于Google Finance图表的行为)。我已经让功能运作起来了,但只能在xy空间中绘制brush。我通过首先向brush变量添加一个y比例尺来实现这一点:
var brush = d3.svg.brush()
    .x(x2)
    .y(y2)
    .on("brush", brush);

这使得 brush.extent() 返回以下多维数组: [ [x0, y0], [x1, y1] ]。然后我在 brush() 函数中使用这些数据来重新定义焦点图表的 x 和 y 域:

function brush() {
  var extent = brush.extent();
  x.domain(brush.empty() ? x2.domain() : [ extent[0][0], extent[1][0] ]);
  y.domain(brush.empty() ? y2.domain() : [ extent[0][1], extent[1][1] ]);
  focus.select("path").attr("d", area);
  focus.select(".x.axis").call(xAxis);
  focus.select(".y.axis").call(yAxis);
}

这个方法可行,但是通过在brush变量中定义y轴比例尺,用户现在可以在焦点图表中拖动“盒子”,而不仅仅是像原始图表中那样只能从西向东拖动。

本质上,我的问题是:我如何获得落在刷子区域内的值的范围,而不是刷子区域本身的范围? 这可能吗?

d3的刷子文档在这里

2个回答

14

我想出了一个解决方案。

我使用了经过刷选的 x.domain 来过滤我的原始数据集。这个新的过滤后的数据集只包含在刷选范围内的值:

// Use x.domain to filter the data, then find the max and min duration of this new set, then set y.domain to that
  x.domain(brush.empty() ? x2.domain() : brush.extent());
  var dataFiltered = data.filter(function(d, i) {
    if ( (d.date >= x.domain()[0]) && (d.date <= x.domain()[1]) ) {
      return d.duration;
    }
  })
  y.domain([0, d3.max(dataFiltered.map(function(d) { return d.duration; }))]);

最后,一定要重新绘制y轴和x轴:
focus.select("path").attr("d", area);
focus.select(".x.axis").call(xAxis);
focus.select(".y.axis").call(yAxis);

3
完美的答案!我能够直接将其插入到我的图表代码中,谢谢。 - fundead

0
一个更简短的方法是在你的 brush.extent() 上使用 d3.scale.invert(),像这样:
var domainExtent = brush.extent().map(function(d){return scale.invert(d);});
var filteredData = data.filter(function(d){return ((d <= domainExtent[1]) && (d >= domainExtent[0]));});

然而,现在d3已经拥有了d3.brushX(),它的设计只允许在东/西方向上进行刷选。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接