宛若重生的gravatar头像
宛若重生 2014-04-25 23:03:46

js点击图片放大效果ImageZoom代码下载

这个效果也叫放大镜效果,最早好像在ppg出现的,之后就有了很多仿制品出来了。
一般用于放大查看商品图片,在凡客,京东商城,阿里巴巴等都有类似的效果。
好处是能在原图附近对图片进行局部放大查看,而且可以通过鼠标控制查看的部位。
这个程序有以下特点:
1,支持使用原图放大或新图片设置大图;
2,大图完成载入前使用原图放大代替,减少操作等待时间;
3,支持鼠标滚动缩放大图;
4,可以通过设置显示范围或显示框大小设置显示尺寸;
5,可以设置是否自动隐藏显示框;
6,支持插件形式的扩展来实现更多的功能。
兼容:ie6/7/8, firefox 3.6.2, opera 10.51, safari 4.0.4, chrome 4.1

效果图如下:

js点击图片放大效果ImageZoom代码下载

程序说明

【基本原理】

首先要有一个img元素作为原图对象,还要有一个容器作为显示框。
显示框里面放另一个img元素作为大图对象,并根据比例设置好尺寸。
当鼠标在原图上移动时,通过对大图进行绝对定位来显示对应的部位,实现类似放大镜的效果。

【图片加载】

先看看使用原图放大加载的过程:
1,加载原图:

1.if ( originPic && originPic != image.src ) {  
2.    image.onload = loadImage;  
3.    image.src = originPic;  
4.} else if ( image.src ) {  
5.    if ( !image.complete ) {  
6.        image.onload = loadImage;  
7.    } else {  
8.        loadImage();  
9.    }  
10.} else {  
11.    return;  
12.}  

_originPic属性记录原图地址,如果设置了原图并且跟元素当前加载的图片不同,就设置onload并加载原图。
否则,如果元素当前有加载图片的话,先通过complete判断是否加载完成,没完成就设置onload,已经完成的话就直接执行加载程序。
最后,没有原图图片的话就退出程序。
2,执行_loadOriginImage加载程序:

1.this._image.onload = null;  
2.this._zoom.src = this._image.src;  
3.this._initLoaded();  

_preload是预载对象,使用的是_loadPreload预载加载程序。

3.当原图加载完成时,执行_loadImage原图加载程序:

1.if ( this._loaded ) {  
2.    this._initLoaded();  
3.} else {  
4.    this._loaded = true;  
5.    if ( this._scale ) {  
6.        this._substitute = true;  
7.        this._zoom.src = this._image.src;  
8.        this._initLoaded();  
9.    }  
10.}  

如果_loaded为true,说明大图已经加载,直接执行_initLoaded程序。

4,当大图预载完成时,执行_loadPreload大图预载程序:

1.this._zoom.src = this._preload.src;  
2.if ( this._loaded ) {  
3.    if ( !this._substitute ) { this._initLoaded(); }  
4.} else {  
5.    this._loaded = true;  
6.}  

如果_loaded是true,说明原图已经加载完,同时_substitute为false即没有使用原图替换的话,就执行_initLoaded程序。
如果原图没有加载完,那么设置_loaded为true标记大图已经加载。

关于图片加载还要注意一个问题,测试以下代码:

1.<script>  
2.var img=new Image  
3.function test(){  
4.    img.onload=function(){alert("load")}  
5.    img.src="http://www.google.com.hk/images/nav_logo8.png"  
6.}  
7.test()  
8.setTimeout(test,3000)  
9.</script> 

在chrome/safari只会弹出一次"load",而其他都是正常的两次,可能是做了优化之类的吧。

当加载完成后,就可以设置相关的对象和参数,这些都在_initLoaded程序中进行。

【加载设置】

在_initLoaded初始化加载设置程序,主要是做触发放大效果前的准备工作。

1.if ( !scale ) { scale = this._preload.width / image.width; }  
2.this._scale = scale = Math.min( Math.max( this._min, scale ), this._max ); 

然后就可以按比例设置大图尺寸:

1.zoom.width = Math.ceil( image.width * scale );  
2.zoom.height = Math.ceil( image.height * scale );

第二步,执行_initViewer初始化显示框程序,设置显示框。
先设置好样式:

1.var styles = { padding: 0, overflow: "hidden" }, p = $$D.getStyle( viewer, "position" );  
2.if ( p != "relative" && p != "absolute" ){ styles.position = "relative"; };  
3.$$D.setStyle( viewer, styles );  
4.zoom.style.position = "absolute"; 

再把显示图插入显示框:

1.if ( !$$D.contains( viewer, zoom ) ){ viewer.appendChild( zoom ); }

第三步,执行_initData初始化数据程序,主要是设置放大时用到的一些参数。
包括用于位置判断的原图坐标:

1.this._rect = $$D.rect( image ); 

用于left/top修正的修正参数:

1.this._repairLeft = image.clientLeft + parseInt($$D.getStyle( image, "padding-left" ));  
2.this._repairTop = image.clientTop + parseInt($$D.getStyle( image, "padding-top" )); 

如果通过rangeWidth和rangeHeight自定义了范围参数,就可以结合放大比例计算出显示尺寸:

1.rangeWidth = Math.ceil( rangeWidth );  
2.rangeHeight = Math.ceil( rangeHeight );  
3.this._viewerWidth = Math.ceil( rangeWidth * scale );  
4.this._viewerHeight = Math.ceil( rangeHeight * scale );  
5.$$D.setStyle( viewer, {  
6.    width: this._viewerWidth + "px",  
7.    height: this._viewerHeight + "px"  
8.}); 

如果没有设置的话,就使用显示框的默认显示尺寸:

1.var styles;  
2.if ( !viewer.clientWidth ) {  
3.    var style = viewer.style;  
4.    styles = {  
5.        display: style.display,  
6.        position: style.position,  
7.        visibility: style.visibility  
8.    };  
9.    $$D.setStyle( viewer, {  
10.        display: "block", position: "absolute", visibility: "hidden"  
11.    });  
12.}  
13.this._viewerWidth = viewer.clientWidth;  
14.this._viewerHeight = viewer.clientHeight;  
15.if ( styles ) { $$D.setStyle( viewer, styles ); }  
16.  
17.rangeWidth = Math.ceil( this._viewerWidth / scale );  
18.rangeHeight = Math.ceil( this._viewerHeight / scale );  

注意,显示范围是通过clientWidth/clientHeight来获取的。
如果显示框是display为none的隐藏状态,就不能直接获取clientWidth/clientHeight。
这种情况下,程序用以下方法获取:
1,记录display/position/visibility的原始值;
2,分别设为"block"/"absolute"/"hidden",这是既能隐藏也能占位的状态;
3,获取参数;
4,重新设回原始值,恢复原来的状态。
得到显示范围后,再配合比例就能得到范围参数了。
ps:这是通用的获取不占位元素尺寸参数的方法,jquery的css也是用这个方法获取width/height的。
比例计算后可能会得到小数,而尺寸大小只能是整数,程序一律使用Math.ceil来取整。

【放大效果】

所有东西都设置好后,就可以执行start设置触发程序了。

程序会自动执行start方法,里面主要是给原图对象的mouseover/mousemove绑定_start程序:

1.var image = this._image, START = this._START;  
2.$$E.addEvent( image, "mouseover", START );  
3.$$E.addEvent( image, "mousemove", START ); 

ps:如果使用attachEvent的话还要注意重复绑定同一函数的问题,这里的addEvent就没有这个问题。

绑定的_start程序,主要是进行一些事件的解绑和绑定:

1.$$E.removeEvent( image, "mouseover", this._START );  
2.$$E.removeEvent( image, "mousemove", this._START );  
3.$$E.addEvent( document, "mousemove", this._MOVE );  
4.$$E.addEvent( document, "mouseout", this._OUT ); 

为了在移出窗口时能结束放大效果,给document的mouseout绑定了_OUT程序:

1.this._OUT = $$F.bindAsEventListener( function(e){  
2.        if ( !e.relatedTarget ) this._END();  
3.    }, this ); 

当鼠标移出document会触发mouseout,如果当前relatedTarget是null的话,就延时执行_end结束程序:

1.var oThis = this, END = function(){ oThis._end(); };  
2.this._END = function(){ oThis._timer = setTimeout( END, oThis.delay ); }; 

在_end程序中,会先执行stop方法,在里面移除所有可能绑定的事件,再执行start方法继续等待触发。

【鼠标滚动缩放】

首先ie是用mousewheel绑定事件的,使用event的wheelDelta来获取滚动参数。
其他浏览器用以下代码测试:

1.<!DOCTYPE html>  
2.<html xmlns="http://www.w3.org/1999/xhtml">  
3.<body style="height:1000px;">  
4.<script>  
5.function test(e){ alert(e.type+":"+e.detail+"_"+e.wheelDelta) }  
6.document.addEventListener( "DOMMouseScroll", test, false );  
7.document.addEventListener( "mousewheel", test, false );  
8.</script>  
9.</body>  
10.</html> 

ps:不明白chrome/safari的detail为什么是0,有其他用途?
而DOMMouseScroll跟mousewheel还有一个不同是前者不能直接绑定元素,后者可以。
即可以elem.onmousewheel,但不能elem.onDOMMouseScroll。

修改比例时,程序参数也需要重新计算。
由于_rangeWidth/_rangeHeight会影响计算的过程,要重新恢复成自定义的默认值:

1.var opt = this.options;  
2.this._rangeWidth = opt.rangeWidth;  
3.this._rangeHeight = opt.rangeHeight;

然后执行_initSize和_initData重新设置尺寸和参数,再执行_move重新定位。
最后记得用preventDefault防止触发页面滚动。

【opera的bug】

测试中发现opera 10.10有两个bug。
分别是img元素设置透明时会看到背景图,用js修改鼠标样式会有问题。
不过这两个问题在10.50都已经修复了,还没升级的赶快升啦。

【maxthon的bug】

用maxthon 2.5.1测试时发现一个问题,测试以下代码:

1.<div id="t" style="width:50px;"></div>  
2.<script>  
3.var t=document.getElementById("t");  
4.t.clientWidth;  
5.t.style.display="none";  
6.alert(t.clientWidth);  
7.</script> 

一般来说用display隐藏后,clientWidth应该是0的,但maxthon貌似没有处理这个情况。
这会影响到程序中clientWidth的判断,不过对一般使用没什么影响。

使用说明

实例化时,必须有一个img元素作为原图对象,和一个容器作为显示框:
var iz = new ImageZoom( "idImage", "idViewer" );

可选参数用来设置系统的默认属性,包括:
属性:    默认值//说明
mode: "simple",//模式
scale: 0,//比例(大图/原图)
max: 10,//最大比例
min: 1.5,//最小比例
originPic: "",//原图地址
zoomPic: "",//大图地址
rangeWidth: 0,//显示范围宽度
rangeHeight:0,//显示范围高度
delay: 20,//延迟结束时间
autoHide: true,//是否自动隐藏
mouse: false,//鼠标缩放
rate: .2,//鼠标缩放比率
onLoad: $$.emptyFunction,//加载完成时执行
onStart: $$.emptyFunction,//开始放大时执行
onMove: $$.emptyFunction,//放大移动时执行
onEnd: $$.emptyFunction//放大结束时执行
初始化后,scale、max、min、originPic、zoomPic、rangeWidth、rangeHeight这些属性需要用reset方法来修改。
还提供了以下方法:
start:开始放大程序(程序会自动执行);
stop:停止放大程序;
reset:修改设置;
dispose:销毁程序。

原文地址:http://www.iteye.com/topic/636664

官方验证:

经验证,该代码完全可用,非常高质量的分享,大家可以放心下载。

   


最代码官方编辑于2016-6-1 9:27:04


打赏

文件名:ImageZoom_ext.rar,文件大小:8.869K 下载
  • /
    • /CJL.0.1.min.js
    • /ImageZoom.js
    • /ImageZoom_ext.htm
最代码最近下载分享源代码列表最近下载
sonofy123  LV9 2020年2月14日
樊樊樊樊樊樊阵雨  LV18 2019年7月4日
wzajx888  LV10 2017年9月14日
小码农tcd  LV16 2017年7月17日
leejunin  LV2 2014年8月18日
最代码官方  LV168 2014年7月23日
最代码最近浏览分享源代码列表最近浏览
onemee  LV36 7月1日
zwj1234  LV1 2023年12月4日
18011700331 2023年10月12日
暂无贡献等级
微信网友_6672184532766720  LV3 2023年10月3日
1599639642  LV3 2023年6月19日
孙晓磊 2023年5月24日
暂无贡献等级
DYDYDY433  LV1 2023年2月16日
端布ejkqwejkqw 2022年12月10日
暂无贡献等级
abcdljw  LV20 2021年12月28日
Dream shadow  LV9 2021年4月16日
顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友