在 D3.js 中缩放或平移时限制域名

9
我已经实现了一个可以缩放和平移的简单D3.js线图。它基于Stephen Bannasch的优秀示例(这里)
我的数据域在x维度上为[0,n]。
如何使用内置的缩放行为(即使用鼠标滚轮事件)将缩放和平移限制在此域中?
例如,我想防止用户在较低端超过0或较高端超过n进行平移操作,他们不应能够在x轴上看到负值,并且希望将缩放限制为相同的窗口。
我发现基于Jason Davies工作的示例使用extent([...],[...],[...])似乎在版本2.9.1中不再起作用。不幸的是,缩放行为目前是API文档中未记录的少数功能之一。
欢迎任何指导意见。
PS. 我在D3.js邮件列表上发布了相同的问题,但没有得到回答:https://groups.google.com/d/topic/d3-js/w6LrHLF2CYc/discussion。对于交叉发布表示歉意。
2个回答

6
很遗憾,Bill所提供的解决方案只解决了一半的问题:虽然它确实抑制了平移,但如果应用缩放,则会导致图形失真。通常无法返回到正确比例和位置的图形。
在下一个版本中,即使滚动到边界,轴的比例也保持不变。
一旦缩放达到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)

1
几乎完美。我遇到的问题是它在缩放操作期间没有效果。如果您在接近右侧限制时放大,将光标放在可见区域的左边缘并缩小:可见区域的右边缘将超出预期的限制。我认为,为了得到完整的解决方案,您需要朝另一个方向进行而不是简单地接受/拒绝翻译的更改。从域限制计算出合法的翻译范围,并限制翻译值。 - mdaoust

0

在重绘时,您只需要限制域名即可。以下代码将防止图表被缩放到其初始域之外(如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)]);

    ....

1
我知道这篇帖子很旧了,但是提醒一下:你引用的链接让我可以在Chrome 29.0中自由缩放和平移。 - SgtPooki
1
使用此示例,在平移时图形会缩放。 - Martins Balodis

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