在javascript中缩放到没有画布的光标

Vey*_*Vey 3 javascript css zooming

我有一个<img>在鼠标滚轮滚动时放大的,通过调整transform: scale(). 我希望缩放就像在谷歌地图中一样,你可以缩放到鼠标光标所在的位置,而不是图像的中心。不过,我不想使用画布,只是为了学习体验(这也是我发现的其他问题没有真正帮助的原因)。

我设置了一个JSFiddle来演示这个问题。我的思考过程如下:当放大 10% 时,图像从图像中心向各个方向扩展 10%。这意味着,例如,左右边缘将在每个方向上移动原始宽度的 5%。因此,我尝试像这样解决问题:

  1. 计算鼠标与图像中心的偏移
  2. 通过将鼠标偏移与缩放系数相乘并除以二来计算新的图像偏移(顶部和左侧)
  3. 应用抵消并看着它用一百万个燃烧的太阳的力量把它炸毁我的脸

似乎我只是找不到适合的公式或算法。

Vey*_*Vey 7

最终我自己弄明白了,尽管只是通过查看现有的解决方案。这是仅包含基本要素的JSFiddle

这个想法是先设置transform-origin: 0 0。这确保在缩放时,图像向下和向右扩展,而不是将宽度的增加分布在所有四个边上。请注意,它不会重新定位图像,它只会更改所有转换的原点

此外,这个 JSFiddle 假设图像的上边距和左边距与容器元素的上边距和左边距对齐。如果图像应该在缩放之前重新定位,这应该完成transform: translate()translateX并且translateY需要相应地更新和值。

逻辑的核心是这样的:

  // Track the percentage change between the old
  // and the new scale of the image
  const ratio = 1 - nextScale / currentScale

  // get the current mouse offset
  const {
    clientX,
    clientY
  } = event

  // The += here is extremely important!
  // The new 2D translation values are derived from the difference
  // between mouse cursor position and current (!) 2D translation.
  // So where is the mouse cursor relative to the translated image
  // This difference is then adjusted by the % change of the scaling
  translateX += (clientX - translateX) * ratio
  translateY += (clientY - translateY) * ratio

  /*
  This would work for the first wheel scroll. But afterwards, the 
  image will not be translated enough to offset the zooming because 
  we're not taking into account the existing translation
  translateX += (clientX - translateX) * ratio
  translateY += (clientY - translateY) * ratio
  */
Run Code Online (Sandbox Code Playgroud)

所以总结一下所需的步骤:

  1. 计算下一个比例
  2. 计算当前鼠标相对于翻译图像的偏移量
  3. 为缩放的变化调整鼠标偏移,例如, const percentChange = 1 - nextScale / currentScale
  4. 将调整后的鼠标偏移添加到现有值中 translate()
  5. 应用转换(缩放和平移)

链接的 JSFiddle 还包括 Lodashtransition: transform 330ms ease-in-out;并使滚动更平滑并且不会过多地影响浏览器性能。