JavaScript 放大镜 - 移动镜片
May 14th, 2010
Add Comment
JavaScript 放大镜是我成为前端后写的第一个组件, 从中学到了很多东西. 现在已经过去超过半年, 我希望能在自己仍有印象的时候, 整理和重新思考其中的一些处理方法, 将它改进, 并将这些想法写出来.
放大镜并不是一个难以实现的效果, 只是因为牵涉到一些精确的数值计算, 显得比较繁琐. 在未来的一段日子, 我会不定期地写关于 JavaScript 放大镜系列的文章, 每次讲一个点, 由点及面, 最后完成整个效果.
本次我们先了解如何在缩略图上移动镜片. (这是 DEMO)
缩略图和镜片组成的 DOM 结构如下.
<a id="thumb" href="#"> <img src="http://img.alibaba.com/photo/291909368/Free-Shipping-Popular-ladies-shoes-Tote-shoes-paypal-accept-201001.jpg" alt="Thumbnail" /> <span id="glass"></span> </a>
我在缩略图容器中放置图片和镜片节点, 以缩略图容器作为相对位置参考, 在触发 mousemove 事件时修改镜片的位置. 换个说法, 我们要解决的问题是, 算出镜片左上角的在缩略图容器中的位置. 计算镜片位移的 JavaScript 代码如下.
/** * 获取镜片在放大目标元素上的位置 * @param ev 触发的事件 * @param thumb 缩略图对象 * @param glass 镜片对象 * @return x:镜片在放大目标元素上的横向位置, y:镜片在放大目标元素上的纵向位置 */ function getGlassOffset(ev, thumb, glass) { var offset = { left:0, top:0 }; // 偏移量 var thumbOffset = getCumulativeOffset(thumb); // 鼠标在页面上的位置 var mousePoint = getMousePoint(ev); // 镜片实际尺寸 var glassSize = getSize(glass); // 简缩图实际尺寸 var thumbSize = getSize(thumb); // 光标横向位置 var cursorX = mousePoint.x - thumbOffset.left; // 镜片横向偏移量 offset.left = cursorX - glassSize.width / 2; if(offset.left < 0) { offset.left = 0; } else if(offset.left > thumbSize.width - glassSize.width) { offset.left = thumbSize.width - glassSize.width; } // 光标纵向位置 var cursorY = mousePoint.y - thumbOffset.top; // 镜片纵向偏移量 offset.top = cursorY - glassSize.height / 2; if(offset.top < 0) { offset.top = 0; } else if(offset.top > thumbSize.height - glassSize.height) { offset.top = thumbSize.height - glassSize.height; } return offset; }
镜片左上角在缩略图容器中的位置 = 鼠标位置 - 缩略图左上角位置 - 镜片尺寸的一半
当镜片在容器外, 将镜片靠边. 全部代码请窥视 DEMO. (知道我为何上一篇写通过 JS 获取鼠标位置了吧?)
留个课后思考题, 当镜片带边框时, 如何保证边框不影响镜片移动时的精确度?
声明: 本文采用 BY-NC-SA 协议进行授权. 转载请注明转自: JavaScript 放大镜 - 移动镜片

嗯 这个很好用
这个在IE7和8下面好像很占CPU。
以前用过jqzoom,还有内存泄露的问题,而且非常严重。不知道你这个有没有内存泄露。希望你这个好用。我的某个程序上本来用了jqzoom最后不得不去掉这个功能。
@煮透社
阿里和淘宝的商铺图片被点击后, 应该是新页打开预览的啊. 而现在这个放大镜效果可以放在加载完的时候进行初始化, 以免影响其他元素的加载.
@bolo
现成的不敢用. 我是用 margin 来做的.
@map
如果镜片的边是 #glass {border:2px solid #999;}
那他的外边距是 #glass {margin:0 -2px -2px 0;}
当镜片带边框时, 如何保证边框不影响镜片移动时的精确度? #glass {margin:0 2px 2px 0;}这样行吗?
这个体验不错
镜片 height 和 width 都确定,
镜片 {
position: relative;
width: Xpx;
height: Ypx;
}
用 JavaScript 改变 top 和 left 的位置,top = 图片 height - 鼠标 Y 坐标 - X/2,left = 图片 width - 鼠标 X 坐标 -Y/2
是不是通过 background-position 的改变来做局部放大效果?这类 library 不是有很多现成的么?还要重新做一个?
好的!谢谢大大分享高级东西!
点击图片放大,让我想起阿里巴巴店铺里的商品图片展示,动态效果虽然好看,可是总觉得很拖沓,不够爽朗,而且公司的IE6用起来那叫痛苦。这些效果还是适可而止为好。
谢谢分享这么高级的东东:)
顶……
来顶一个~~
继续跟着学习
学习学习! JS不懂。。。
偶来打酱油~
很牛的说
阿里巴巴的前端就是与众不同,哈哈
嗨。。帅。。。
对于带有产品展示的站点来说
这是个很好的设计~
这个效果不错,
还带了课后题。
这个效果很好玩,图片站千万不能错过
谢谢师兄分享~
学习了