通过刷新鼠标移动焦点+上下文缩放问题

时间:2014-09-03 22:28:48

标签: javascript svg d3.js zooming

完整代码位于jsfiddle。 问题是当顶部和底部图表中的缩放鼠标移动不匹配时,即底部的移动圆圈不应超出通过刷涂选择的区域。我正在更新移动点,如下所示:

  focus.on "mousemove", () ->
     xPos = d3.mouse(this)[0]
     updateMovingPoints(xPos)
  context.on "mousemove", () ->
     xPos = d3.mouse(this)[0]
     updateMovingPoints(xPos)

enter image description here

如您所见,底部鼠标悬停与顶部图表不匹配,即超出缩放区域。

1 个答案:

答案 0 :(得分:1)

我的解决方案主要使用AmeliaBR的建议将xPos从一个x-scale转换为另一个x-scale,我使用xScale(xScale2.invert(xPos))进行转换,然后将此修改后的x位置传递给updateMovingPoints

D3时间刻度上的

scale.invert从原始数据(文档here)中获取日期,我们可以立即重新缩放,以使用不同的比例转换为SVG x坐标

这是小提琴:http://jsfiddle.net/henbox/pusauc5q/10/

首先,我将updateMovingPoints函数拆分为两个updateMovingPointsTopupdateMovingPointsbottom,因为更新底部(上下文)图表总是很容易,而更新顶部(焦点)是棘手的一点。

  updateMovingPointsTop = (xPos) ->    
    focusLine1 = focus.select(".line1").attr("d", line1(data))
    focusLine2 = focus.select(".line2").attr("d", line2(data))
    updatePointPosition(xPos, focusLine1, focusCircles[0])
    updatePointPosition(xPos, focusLine2, focusCircles[1])

  updateMovingPointsBottom = (xPos) ->      
    contextLine1 = context.select(".line1").attr("d", line3(data))
    contextLine2 = context.select(".line2").attr("d", line4(data))
    updatePointPosition(xPos, contextLine1, contextCircles[0])
    updatePointPosition(xPos, contextLine2, contextCircles[1])

然后,只有当鼠标移动到底部(上下文)时,我才想进行一些计算,以找出底部xPos应该如何转换为顶部x-scale:

updateMovingPointsTop(calculatexPosTop(xPos))

calculatexPosTop函数本身有一些注释要解释。但基本上它将xPos从底部x刻度转换为顶部x刻度,并且如果它位于边界之外,则设置为该顶部刻度的最小\最大范围。在定义比例时,边界由range计算:

# The min and max extents (x coords) of the 'context' (top chart)
xScaleTopRange = xScale.range()
minExtent = xScaleTopRange[0]
maxExtent = xScaleTopRange[1]

密钥calculatexPosTop函数如下所示:

# When mousemoving on the bottom chart, calculate where the equivaluent point is on the top chart
calculatexPosTop = (xPos) ->  
  # The translation of the 'context' x-scale (xScale2) to the 'focus' x-scale (xScale)
  # Note that when there's no zooming, xScale and xScale2 are the same so xPosInFocusScale = xPos
  xPosInFocusScale = xScale(xScale2.invert(xPos))
  # Check if the translated point lies outside the extents of the focus scale's range
  if xPosInFocusScale < minExtent
    minExtent
  else if xPosInFocusScale > maxExtent
    maxExtent
  else
    xPosInFocusScale

修改

我意识到我错过了解决方案的一部分:当放大时,沿顶部图表移动并未将点保持在拉丝区域内。小提琴链接现在更新了此修复程序。

这涉及添加另一个与calculatexPosBottom非常相似的函数calculatexPosTop,但我没有使用scale.range来获取最大和最小范围,而是使用brush.extent() brushed用于查找拉丝区域的“大小”:

# Get the x-limits of the brush
brushExtent = brush.extent()
# Convert using the x-scale to get SVG coordinates
minBrushExtent = xScale2(brushExtent[0])
maxBrushExtent = xScale2(brushExtent[1])

...然后我使用刷子min \ max范围,如下所示:

calculatexPosBottom = (xPos) ->  
  xPosInContextScale = xScale2(xScale.invert(xPos))
  # Check if there is no brushed area (ie the extent is [0, 0])
  # The brush extent is defined in the 'brushed' function
  if minBrushExtent == maxBrushExtent
    # If there is no brush, just use the same points on both scales
    xPos
  else if xPosInContextScale < minBrushExtent
    minBrushExtent
  else if xPosInContextScale > maxBrushExtent
    maxBrushExtent
    ...