JavaScript 放大镜 - 移动镜片

May 14th, 2010 Add Comment
image

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 放大镜 - 移动镜片

  1. http://0.gravatar.com/avatar/497ea247993bf5d350c9aa7796c6eb81?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    嗯 这个很好用

  2. http://0.gravatar.com/avatar/a2bbc81a3c9d63e2bd1a621b5e1a641a?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    这个在IE7和8下面好像很占CPU。
    以前用过jqzoom,还有内存泄露的问题,而且非常严重。不知道你这个有没有内存泄露。希望你这个好用。我的某个程序上本来用了jqzoom最后不得不去掉这个功能。

  3. http://0.gravatar.com/avatar/490cf262668eebb0f0f1a50d9d48d702?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    @煮透社
    阿里和淘宝的商铺图片被点击后, 应该是新页打开预览的啊. 而现在这个放大镜效果可以放在加载完的时候进行初始化, 以免影响其他元素的加载.

    @bolo
    现成的不敢用. 我是用 margin 来做的.

    @map
    如果镜片的边是 #glass {border:2px solid #999;}
    那他的外边距是 #glass {margin:0 -2px -2px 0;}

  4. http://0.gravatar.com/avatar/27faf612130842a226d98553912ae283?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    当镜片带边框时, 如何保证边框不影响镜片移动时的精确度? #glass {margin:0 2px 2px 0;}这样行吗?

  5. http://1.gravatar.com/avatar/792a5ff64cdc12c488465495da66af0b?s=32&d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G
  6. http://0.gravatar.com/avatar/2a9c4f525050372a6fe0b10ce4fe8957?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    镜片 height 和 width 都确定,
    镜片 {
    position: relative;
    width: Xpx;
    height: Ypx;
    }
    用 JavaScript 改变 top 和 left 的位置,top = 图片 height - 鼠标 Y 坐标 - X/2,left = 图片 width - 鼠标 X 坐标 -Y/2

  7. http://0.gravatar.com/avatar/2a9c4f525050372a6fe0b10ce4fe8957?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    是不是通过 background-position 的改变来做局部放大效果?这类 library 不是有很多现成的么?还要重新做一个?

  8. http://1.gravatar.com/avatar/fe17613a53cc59eea0a1079474f14a3a?s=32&d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    好的!谢谢大大分享高级东西!

  9. http://1.gravatar.com/avatar/10f414264bc1d7fd3b5dcddb321bff08?s=32&d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    点击图片放大,让我想起阿里巴巴店铺里的商品图片展示,动态效果虽然好看,可是总觉得很拖沓,不够爽朗,而且公司的IE6用起来那叫痛苦。这些效果还是适可而止为好。

  10. http://0.gravatar.com/avatar/8eb05daeae832f4d0d5fa7dd5ff987dd?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    谢谢分享这么高级的东东:)

  11. http://0.gravatar.com/avatar/070a72b3ecc85c8e4fbedb9dc91c5fc1?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    Eric :
    来顶一个~~

    顶……

  12. http://0.gravatar.com/avatar/c2dd80f8c99ef13c3291e593f13aa303?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G
  13. http://0.gravatar.com/avatar/e8f87528ed0a0eaba60009f8580df401?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    继续跟着学习

  14. http://0.gravatar.com/avatar/6ae83ef4bfaa6f98356a5187b6f171f6?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    学习学习! JS不懂。。。

  15. http://0.gravatar.com/avatar/03487f19b54904dbf98f5ba4f10b04bb?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    偶来打酱油~

  16. http://1.gravatar.com/avatar/b343c26c40ea021116b4ab8a62233b25?s=32&d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G
  17. http://1.gravatar.com/avatar/f54f7e8880a77d9be41f85c973d4b7d0?s=32&d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    阿里巴巴的前端就是与众不同,哈哈

  18. http://1.gravatar.com/avatar/9b26e89d5399072dca1ccf7171f8915a?s=32&d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    :evil: 代码收藏了。

  19. http://1.gravatar.com/avatar/b2986defdd28dcaa196e317a94d82e31?s=32&d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    嗨。。帅。。。

  20. http://1.gravatar.com/avatar/94edba5ccaf4f54d0891cf3a7b1e1280?s=32&d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    对于带有产品展示的站点来说
    这是个很好的设计~

  21. http://1.gravatar.com/avatar/fa7f6e086d0164f7a5c41a79df6bd3ee?s=32&d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    这个效果不错, :smile: 还带了课后题。

  22. http://1.gravatar.com/avatar/9d9477ecc62b02e1462344209df591c6?s=32&d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    这个效果很好玩,图片站千万不能错过

  23. http://0.gravatar.com/avatar/eafff4918fffe6108e0f1ce887ee42e6?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    谢谢师兄分享~
    学习了 :razz:

  1. Loading...