有些时候我们在看一些图的时候,下面会有一个全局的图,然后它上面有一个选区,我们移动它,可以看到不同部分的细节,这种东西在d3.js里面叫brush,例如下图就有一个brush:

brush有一维的和二维的,今天我们主要来看看一维的brush,它主要是配合zoom一起实现的,今天看看一般的实现套路:

绘制两套坐标和内容

这种带brush的,一般要绘制两套坐标,一套是用来显示上面的可缩放坐标轴,一套是显示下面固定的全局坐标轴:

内容则是根据坐标轴来,同样绘制两套:

zoom和brush

绘制了基本的形状和坐标,现在就要开始添加zoom和brush这两个核心功能了:

zoom是绑定在svg上,监听svg上的zoom事件:

brush则是放在下面的坐标中,监听下面坐标的brush事件:

translateExtent表示zoom的缩放范围,如果不设置,就是[-∞,+∞]。设置了[[0,0],[width,height]]之后,只会在有内容的范围缩放,移动。

extent表示视图范围,默认为extend[[0,0],[width,height]]表示视图大小和实际大小一致,下面看一个extend:[[0,0],[width/2,height/2]]:

background Layer 1 extend:[[0,0],[width/2,height/2]] 视图大小 真实大小 width height 2*width 2*height

extend:[[0,0],[width/2,height/2]]表示此时的真实大小为视图的2倍。

brush事件

brush可以拖动,或者移动两边的刷子来控制范围,这些在brush事件中会被设别为mousemove,mouseup,但是诸如zoom类的事件,会被识别为zoom,因此在brush事件中要将zoom事件剔除。

d3.event.selection可以得到当前brush选择范围, x.domain(s.map(x2.invert, x2));中的invert是一种将range映射到domain的方法,可以得到当前选取(range)的domain。(可以参考d3.js中apply,invert,rescaleX等方法。)

因为domain变化了,focus.select(".area").attr("d", area);设置当前选取的图形;focus.select(".axis--x").call(xAxis);重新设置坐标轴。

现在还有一个问题,虽然zoom区坐标,图形(domain)已经发生了改变,但是zoom区并没有记住当前的这些形变,因为zoom区获是通过d3.event.transform来获取形变,而不是通过domain,因此需要把当前brush的domain的变化转变成形变。也就是svg.call(zoom.transform, d3.zoomIdentity.scale(width / (s[1] - s[0])).translate(-s[0], 0));了

zoom事件

zoom中的缩放,移动,会被识别为mouseup,mousemove,wheel等,但是brush相关的会被识别为brush,因此要屏蔽brush相关事件。

通过d3.event.transform获取当前zoom区的形变,然后通过rescaleX得到方向range后的domain坐标。(可以参考d3.js中apply,invert,rescaleX等方法。),也就是形变后的domain坐标。

focus.select(".area").attr("d", area);设置图像;focus.select(".axis--x").call(xAxis);重新生成坐标。

brush.move, x.range().map(t.invertX, t)中的invertX是得到形变反向X坐标的方法,也就是让range根据当前的形变,得到一个反方向坐标范围。

其他文章

0
我要评论

评论

返回
×

我要评论

回复:

昵称:(昵称不超过20个字)

图片:

提交
还可以输入500个字