2012-12-20 30 views
17

我正在使用d3.js,并且通过修改this example来处理拉丝面积图。除了基于笔刷的x轴变化之外,我还希望根据笔刷内数据的y值重新绘制图表的y轴(类似于a Google Finance chart的行为)。更新拉丝面积图的y轴

我已经获得了功能性的工作,但只有一种方式可以在x和y空间中绘制画笔。我这样做:首先使y缩放增加了brush变量:

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的笔刷文档是here

回答

13

我想出了一个解决方案。

我用画笔过滤的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(),它只允许通过设计在东/西方向刷牙。