宛若重生的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日
最代码官方  LV167 2014年7月23日
最代码最近浏览分享源代码列表最近浏览
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日
muimuimui  LV9 2021年2月13日
顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友