在JavaScript中无需画布即可缩放到光标 [英] Zoom to cursor without canvas in javascript

查看:40
本文介绍了在JavaScript中无需画布即可缩放到光标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个< img> ,可以通过调整 transform:scale()在鼠标滚轮滚动时缩放.我希望缩放效果与Google Maps一样,在这里您可以缩放到鼠标光标所在的位置,而不是图像的中心.我只是为了学习经验而不想使用画布(这也是为什么我发现的其他问题并没有真正帮助的原因.)

I have an <img> that is zoomed upon mousewheel scrolling, by adjusting transform: scale(). I want the zooming to be like in Google Maps, where you zoom to where the mouse cursor is, not to the center of the image. I'd like to not use canvas though, just for the learning experience (that's also why the other questions I found did not really help).

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

I set up a JSFiddle to demonstrate the problem. My thought process was as follows: when zooming in by 10%, the image expands in all directions, from the center of the image, by 10%. That means that e.g., the left and right edge will travel 5% of the original width in each direction. I therefore tried to solve the problem like so:

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

似乎我找不到适合的公式或算法.

It seems that I just can't find a formula or algorithm that fits.

推荐答案

最终,尽管仅通过查看现有解决方案,我还是自己解决了这个问题.这是 JSFiddle ,其中仅包含要点.

Eventually I figured it out myself, although only by looking at existing solutions. Here is the JSFiddle that contains only the essentials.

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

The idea is to first set transform-origin: 0 0. This makes sure that, upon zooming, the image expands down and right, instead of distributing the increase in width over all four sides. Note that it does not reposition the image, it just changes the origin for all transformations.

此外,此JSFiddle假定图像的顶部和左侧边缘与容器元素的顶部和左侧边缘对齐.如果在缩放发生之前应重新定位图像,则应通过 transform:translate()完成,并且需要将 translateX translateY 值已相应更新.

Additionally, this JSFiddle assumes that the top and left margins of the image are aligned with the top and left margins of the container element. If the image should be repositioned before zooming occurs, this should be done through transform: translate() and the translateX and translateY values need to be updated accordingly.

逻辑的核心是这样:

  // 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 mousewheel 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
  */

因此,总结所需的步骤:

So to summarize the required steps:

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

这篇关于在JavaScript中无需画布即可缩放到光标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆