18

我正在使用 d3.js,并且我正在通过修改此示例来处理拉丝区域图。除了根据画笔改变 x 轴之外,我还希望根据画笔内数据的 y 值重新绘制图表的 y 轴(类似于Google Finance 图表的行为) .

我已经使该功能正常工作,但只能以能够在 x 和 y 空间中绘制画笔的方式进行。我首先通过向brush变量添加 ay 比例来做到这一点:

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

这可行,但是通过在画笔变量中定义 y 比例,用户现在可以在焦点图表中拖动“框”,而不是像原始图表中那样只能从西向东拖动。

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

d3的刷机文档在这里

4

2 回答 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);
于 2012-12-21T00:06:26.727 回答
0

一个更短的可能性是d3.scale.invert()在你brush.extent()喜欢的地方使用:

var domainExtent = brush.extent().map(function(d){return scale.invert(d);});
var filteredData = data.filter(function(d){return ((d <= domainExtent[1]) && (d >= domainExtent[0]));});

However, by now d3 has gained d3.brushX(), which only allows brushing in East/West direction by design.

于 2017-08-11T12:35:34.037 回答