我正在使用全屏图像查看器,我将在此处临时打开一个开发 URL:
http://www.jungledragon.org/apps/jd3/image/704/great_grey_owl.html/zoom
此查看器具有响应性,可根据您的浏览器宽度/高度进行缩放。它的主要功能之一是能够使用鼠标滚轮放大和缩小图像。这个想法不是基于中心的缩放,而是基于原点进行缩放,即鼠标的坐标,允许您放大图像的特定区域。
如何重现问题
如果您打开上面的 URL 并快速使用鼠标滚轮,它可能看起来工作正常。但是,我使用的数学有点偏离。以下是重现该问题的方法:
- 打开上面的网址
- 将鼠标悬停在猫头鹰的左眼上
- 使用鼠标滚轮缩放一步,它应该完全放大到眼睛
- 将鼠标放在猫头鹰的喙上
- 使用鼠标滚轮再放大一步
您现在应该注意到,第二个缩放步骤并没有完全进入猫头鹰的喙,它似乎在水平和垂直方向上都略微偏离了。我认为这是数学不好的结果。
这个怎么运作
这是处理这一切的javascript:
http://www.jungledragon.org/apps/jd3/js/jd3-slideshow.js
我正在捕获鼠标滚轮事件。根据它的方向,我正在增加或减少缩放级别。实际的缩放只不过是应用一个使用 CSS3 变换来缩放图像的 CSS 类:
&.grow1 { @include jd-scale(1); }
&.grow2 { @include jd-scale(1.5); }
&.grow3 { @include jd-scale(2.0); }
&.grow4 { @include jd-scale(2.5); }
&.grow5 { @include jd-scale(3.0); }
注意:上面是对 SASS mixin 的调用,它转换为transform:scale的正确供应商前缀。
以上完成了基本的缩放没有问题。但是,要使基于原点的缩放成为可能,还需要几个步骤。在进行实际缩放时,我首先使用 javascript 设置缩放的原点transform-origin。这是我设置它的辅助函数:
function zoomOrigin(selector, originStr) {
selector.css({'-webkit-transform-origin': originStr});
selector.css({'-moz-transform-origin': originStr});
selector.css({'-ms-transform-origin': originStr});
selector.css({'-o-transform-origin': originStr});
selector.css({'transform-origin': originStr});
}
这个问题的核心是计算正确的原点。计算这个值有两点值得一提:
- 绝对坐标(即 X 和 Y)是相对于图像的,而不是相对于页面的
- 原点的计算应该考虑到图像已经根据当前缩放状态放大/缩小
原点计算基于 mousemove 事件实时发生。这是这样做的方法,删除了不相关的部分:
$("#image-container img").mousemove(function(e) {
// user has moved their mouse. in case of zooming or panning, this means that the
// origin (center point) of those interactions need to be recalculated
// calculate the mouse offset within the zoomable object (which is different than the page-level offset)
// this relies on the parent of the element having position:relative set
var parentOffset = $(this).offset();
zoomOriginX = e.pageX - parentOffset.left;
zoomOriginY = e.pageY - parentOffset.top;
// recalculate the width and height of the image given the current zoom level
width = $(this).outerWidth() + (1 + ((zoomLevelCurrent - 1)*0.5) * $(this).outerWidth());
height = $(this).outerHeight() + (1 + ((zoomLevelCurrent - 1)*0.5) * $(this).outerHeight());
// calculate origin percentages based on zoomed width and height
// the zoom methods rely on these variables to be set
zoomOriginPercX = (zoomOriginX / width * 100);
zoomOriginPercY = (zoomOriginY / height * 100);
});
该方法的主要目的是正确设置全局变量zoomOriginPercX和zoomOriginPercY,它们用于在缩放之前设置原点(百分比)。
从数学的角度来看,我的想法是简单地计算图像的缩放宽度,并使用偏移 X 和 Y 来得出可靠的原点百分比。正如问题陈述所示,我非常接近正确的计算,但有些东西不对劲。
尽管缩放目前效果很好,但我希望它是完美的。它将成为一个非常强大的图像查看器,它非常容易实现,也适用于其他人。