在 javascript 中没有 canvas 的情况下缩放至光标
Zoom to cursor without canvas in javascript
我有一个 <img>
,它通过调整 transform: scale()
在鼠标滚轮滚动时缩放。我希望缩放就像在 Google 地图中一样,缩放到鼠标光标所在的位置,而不是图像的中心。不过,我不想使用 canvas,只是为了学习经验(这也是为什么我发现的其他问题没有真正帮助的原因)。
我设置了一个JSFiddle来演示问题。我的思考过程是这样的:当放大10%时,图像向四面八方扩展,从图像中心开始,扩展10%。这意味着,例如,左右边缘将在每个方向上移动原始宽度的 5%。因此,我试图像这样解决问题:
- 计算鼠标距图像中心的偏移量
- 通过将鼠标偏移量乘以缩放因子并除以二来计算新的图像偏移量(顶部和左侧)
- 应用偏移,看着它用一百万个燃烧的太阳的力量炸毁我的脸
看来我就是找不到合适的公式或算法。
你可以使用 transform-origin : <position of your mouse pointer>
:
transform-origin : 0% 0%
点在左上角。
transform-origin : 100% 100%
点在右下角。
这是我做的一个例子:https://jsfiddle.net/zez538L8/4/
javaScript :
var currentzoom = 1;
function zoom(delta, e) {
var img = document.getElementById("test");
var width = img.offsetWidth; //calculating the size of the img (in px)
var height = img.offsetHeight;
var x = event.offsetX; //calculating the position of the mouse pointer on the picture (in px)
var y = event.offsetY;
var xpercent = x*100/width; //calculating the position of the mouse pointer on the picture (in %)
var ypercent = y*100/height;
img.style.transform = "scale("+currentzoom+")"; //scaling the picture
img.style.transformOrigin = xpercent + "% "+ ypercent +"%"; //transform-origin
currentzoom += delta;
}
最终我自己弄明白了,尽管只是通过查看现有的解决方案。这是仅包含要点的JSFiddle。
思路是先设置transform-origin: 0 0
。这确保了在缩放时图像会向下和向右扩展,而不是将宽度的增加分布在所有四个边上。请注意,它不会重新定位图像,它只是 changes the origin for all transformations.
此外,此 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
*/
所以总结一下所需的步骤:
- 计算下一个尺度
- 计算当前鼠标相对于翻译图像的偏移量
- 根据缩放比例的变化调整鼠标偏移量,例如
const percentChange = 1 - nextScale / currentScale
- 将调整后的鼠标偏移添加到
translate()
的现有值
- 应用转换(缩放和平移)
链接的 JSFiddle 还包括 Lodash 和 transition: transform 330ms ease-in-out;
以使滚动更平滑并且不会对浏览器性能造成太大影响。
我有一个 <img>
,它通过调整 transform: scale()
在鼠标滚轮滚动时缩放。我希望缩放就像在 Google 地图中一样,缩放到鼠标光标所在的位置,而不是图像的中心。不过,我不想使用 canvas,只是为了学习经验(这也是为什么我发现的其他问题没有真正帮助的原因)。
我设置了一个JSFiddle来演示问题。我的思考过程是这样的:当放大10%时,图像向四面八方扩展,从图像中心开始,扩展10%。这意味着,例如,左右边缘将在每个方向上移动原始宽度的 5%。因此,我试图像这样解决问题:
- 计算鼠标距图像中心的偏移量
- 通过将鼠标偏移量乘以缩放因子并除以二来计算新的图像偏移量(顶部和左侧)
- 应用偏移,看着它用一百万个燃烧的太阳的力量炸毁我的脸
看来我就是找不到合适的公式或算法。
你可以使用 transform-origin : <position of your mouse pointer>
:
transform-origin : 0% 0%
点在左上角。transform-origin : 100% 100%
点在右下角。
这是我做的一个例子:https://jsfiddle.net/zez538L8/4/
javaScript :
var currentzoom = 1;
function zoom(delta, e) {
var img = document.getElementById("test");
var width = img.offsetWidth; //calculating the size of the img (in px)
var height = img.offsetHeight;
var x = event.offsetX; //calculating the position of the mouse pointer on the picture (in px)
var y = event.offsetY;
var xpercent = x*100/width; //calculating the position of the mouse pointer on the picture (in %)
var ypercent = y*100/height;
img.style.transform = "scale("+currentzoom+")"; //scaling the picture
img.style.transformOrigin = xpercent + "% "+ ypercent +"%"; //transform-origin
currentzoom += delta;
}
最终我自己弄明白了,尽管只是通过查看现有的解决方案。这是仅包含要点的JSFiddle。
思路是先设置transform-origin: 0 0
。这确保了在缩放时图像会向下和向右扩展,而不是将宽度的增加分布在所有四个边上。请注意,它不会重新定位图像,它只是 changes the origin for all transformations.
此外,此 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
*/
所以总结一下所需的步骤:
- 计算下一个尺度
- 计算当前鼠标相对于翻译图像的偏移量
- 根据缩放比例的变化调整鼠标偏移量,例如
const percentChange = 1 - nextScale / currentScale
- 将调整后的鼠标偏移添加到
translate()
的现有值
- 应用转换(缩放和平移)
链接的 JSFiddle 还包括 Lodash 和 transition: transform 330ms ease-in-out;
以使滚动更平滑并且不会对浏览器性能造成太大影响。