我正在制作一个全屏图片查看器,我暂时在这里打开一个开发者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类而已:
这种方法的主要目的是正确地设置全局变量zoomOriginPercX和zoomOriginPercY,用于在缩放之前设置原点(百分比)。
从数学角度来看,我的想法很简单,就是计算图像的缩放宽度,并使用偏移量X和Y得出可靠的原点百分比。正如问题陈述所示,我已经接近正确的计算结果,但还有些偏差。
尽管缩放目前运行良好,但我希望它能变得完美。这将成为一个非常强大的图像浏览器,也很容易实现,即使对于其他人也是如此。
http://www.jungledragon.org/apps/jd3/image/704/great_grey_owl.html/zoom
该查看器是响应式的,并根据您浏览器的宽度/高度进行缩放。其中一个关键功能是能够使用鼠标滚轮对图像进行缩放。与基于中心的缩放不同,我们根据原点(即鼠标的坐标)进行缩放,从而可以将图像放大到特定区域。
如何再现问题
如果您打开上面的URL并快速尝试一下鼠标滚轮,它可能看起来正常。但是,我使用的数学计算略有偏差。以下是如何再现此问题:
- 打开上面的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的正确的浏览器前缀。
上述代码实现了基本的缩放功能,没有问题。然而,要实现基于原点的缩放,需要进行更多步骤。在实际缩放之前,我首先使用transform-origin在javascript中设置缩放的原点。以下是我的帮助函数:
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得出可靠的原点百分比。正如问题陈述所示,我已经接近正确的计算结果,但还有些偏差。
尽管缩放目前运行良好,但我希望它能变得完美。这将成为一个非常强大的图像浏览器,也很容易实现,即使对于其他人也是如此。