Nil*_*ils 9 javascript charts zoom pan d3.js
我已经实现了一个简单的D3.js折线图,可以进行缩放和平移.它基于Stephen Bannasch 在这里的出色例子.
我的数据域在x维度中是[0,n].
如何使用内置缩放行为(即使用鼠标滚轮事件)限制缩放和平移到此域?
我想阻止用户在低端或者在高端的n上淘汰过去0,例如他们永远不能在x轴上看到负值,并且想要限制缩放到同一个窗口.
基于Jason Davies使用范围([...],[...],[...])找到的示例似乎不再适用于2.9.1版本.不幸的是,缩放行为目前是其他未完成的API文档中未记录的少数功能之一.
任何指针都是受欢迎的.
PS.我在D3.js邮件列表上发布了相同的问题,但没有收到回复:https://groups.google.com/d/topic/d3-js/w6LrHLF2CYc/discussion.为交叉发布道歉.
可悲的是,比尔发布的解决方案只有一半的技巧:虽然它确实抑制了平移,但如果应用了缩放,则会导致图形扭曲.然后通常不可能返回到适当比例和定位的图形.
在以下版本中,即使滚动到边框,也会保持轴的比例.
一旦缩放达到100%,缩放的域将重置为其原始位置.即使中间步骤返回轴的非法参数,这也可确保正确定位.
虽然不完美,但我希望这个脚本可以帮助某人,直到d3(重新)实现此功能.
# x and y are the scales
# xAxis and yAxis are the axes
# graph is the graph you want attach the zoom to
x0 = x.copy()
y0 = y.copy()
successfulTranslate = [0, 0]
zoomer = d3.behavior.zoom()
.scaleExtent([1,2])
onZoom = ->
ev = d3.event # contains: .translate[x,y], .scale
if ev.scale == 1.0
x.domain x0.domain()
y.domain y0.domain()
successfulTranslate = [0, 0]
else
xTrans = x0.range().map( (xVal) -> (xVal-ev.translate[0]) / ev.scale ).map(x0.invert)
yTrans = y0.range().map( (yVal) -> (yVal-ev.translate[1]) / ev.scale ).map(y0.invert)
xTransOk = xTrans[0] >= x0.domain()[0] and xTrans[1] <= x0.domain()[1]
yTransOk = yTrans[0] >= y0.domain()[0] and yTrans[1] <= y0.domain()[1]
if xTransOk
x.domain xTrans
successfulTranslate[0] = ev.translate[0]
if yTransOk
y.domain yTrans
successfulTranslate[1] = ev.translate[1]
zoomer.translate successfulTranslate
graph.select('g.x.axis').call(xAxis)
graph.select('g.y.axis').call(yAxis)
drawBars()
zoomer.on('zoom', onZoom)
# ...
graph.call(zoomer)
Run Code Online (Sandbox Code Playgroud)
您只需要限制重绘的域即可。以下代码将防止图形缩小到超过其初始域(如http://bl.ocks.org/1182434中使用的)。
SimpleGraph.prototype.redraw = function() {
var self = this;
return function() {
self.x.domain([Math.max(self.x.domain()[0], self.options.xmin), Math.min(self.x.domain()[1], self.options.xmax)]);
self.y.domain([Math.max(self.y.domain()[0], self.options.ymin), Math.min(self.y.domain()[1], self.options.ymax)]);
....
Run Code Online (Sandbox Code Playgroud)