ImageZoom 图片放大效果

it2025-03-22  15

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

效果预览

按大图放大放大2倍放大5倍放大10倍 原图: 大图:

 

程序说明

【基本原理】

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

【图片加载】

程序初始化时会先执行_initLoad程序,主要用来载入图片。 由于img在载入之前获取尺寸是不准确的,所以相关参数的计算都要等到图片加载之后。

有两种放大的方式:使用原图放大、用已经放大的新图片。 原图放大的好处是只需加载一个图片,而使用新图片就可以得到更清晰的效果。 根据不同的方式,会选择对应的原图加载程序:

useOrigin  =   ! this ._zoomPic  &&   this ._scale, loadImage  =  $$F.bind( useOrigin  ?   this ._loadOriginImage :  this ._loadImage,  this  );

当没有设置大图但有放大比例时,会自动使用原图放大加载程序。

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

代码 if  ( originPic  &&  originPic  !=  image.src ) {     image.onload  =  loadImage;     image.src  =  originPic; }  else   if  ( image.src ) {      if  (  ! image.complete ) {         image.onload  =  loadImage;     }  else  {         loadImage();     } }  else  {      return ; }

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

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

由于ie6/7的gif图片载入bug,会先重置onload。 然后执行_initLoaded初始化加载设置程序。

使用新图片就复杂一点: 1,加载原图,同上。 2,预载大图:

代码 var  preload  =   this ._preload, zoomPic  =   this ._zoomPic  ||  image.src,     loadPreload  =  $$F.bind(  this ._loadPreload,  this  ); if  ( zoomPic  !=  preload.src ) {     preload.onload  =  loadPreload;     preload.src  =  zoomPic; }  else  {      if  (  ! preload.complete ) {         preload.onload  =  loadPreload;     }  else  {          this ._loadPreload();     } }

_preload是预载对象,使用的是_loadPreload预载加载程序。 预载对象主要用来获取大图的原始尺寸,也是后面原图替换技巧的基础。 如果没有设置大图,说明当前没有设置大图也又没有放大比例,这时就用原图作为大图来用。 加载的方法跟原图类似。 3,当原图加载完成时,执行_loadImage原图加载程序:

if  (  this ._loaded ) {      this ._initLoaded(); }  else  {      this ._loaded  =   true ;      if  (  this ._scale ) {          this ._substitute  =   true ;          this ._zoom.src  =   this ._image.src;          this ._initLoaded();     } }

如果_loaded为true,说明大图已经加载,直接执行_initLoaded程序。 否则设置_loaded为true来标记原图已经加载,如果这时有自定义比例的话,先用原图替换大图。 因为一般大图加载会比较慢,先用原图替换就能立刻操作了,同时设置_substitute属性为true标记使用了替换。 4,当大图预载完成时,执行_loadPreload大图预载程序:

this ._zoom.src  =   this ._preload.src; if  (  this ._loaded ) {      if  (  ! this ._substitute ) {  this ._initLoaded(); } }  else  {      this ._loaded  =   true ; }

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

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

< script > var  img = new  Image function  test(){     img.onload = function (){alert( " load " )}     img.src = " http://www.google.com.hk/images/nav_logo8.png " } test() setTimeout(test, 3000 ) < / script>

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

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

【加载设置】

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

第一步,执行_initSize程序初始化显示图尺寸。 首先修正放大比例:

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

如果没有设置比例,就从预载对象获取的默认尺寸作为大图尺寸。 在图片加载时已经做好“安全措施”,确保这里能获得放大比例。 还可以通过自定义max和min属性来限制比例大小。 然后就可以按比例设置大图尺寸:

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

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

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

再把显示图插入显示框:

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

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

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

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

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

还有范围参数和显示尺寸。 范围参数就是要显示的范围在原图的尺寸,显示尺寸是显示框的显示尺寸。 如果通过rangeWidth和rangeHeight自定义了范围参数,就可以结合放大比例计算出显示尺寸:

代码 rangeWidth  =  Math.ceil( rangeWidth ); rangeHeight  =  Math.ceil( rangeHeight ); this ._viewerWidth  =  Math.ceil( rangeWidth  *  scale ); this ._viewerHeight  =  Math.ceil( rangeHeight  *  scale ); $$D.setStyle( viewer, {     width:  this ._viewerWidth  +   " px " ,     height:  this ._viewerHeight  +   " px " });

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

代码 var  styles; if  (  ! viewer.clientWidth ) {      var  style  =  viewer.style;     styles  =  {         display: style.display,         position: style.position,         visibility: style.visibility     };     $$D.setStyle( viewer, {         display:  " block " , position:  " absolute " , visibility:  " hidden "     }); } this ._viewerWidth  =  viewer.clientWidth; this ._viewerHeight  =  viewer.clientHeight; if  ( styles ) { $$D.setStyle( viewer, styles ); } rangeWidth  =  Math.ceil(  this ._viewerWidth  /  scale ); 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程序:

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

分别对应移入原图对象和在原图对象上移动的情况。 ps:如果使用attachEvent的话还要注意重复绑定同一函数的问题,这里的addEvent就没有这个问题。

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

代码 $$E.removeEvent( image,  " mouseover " this ._START ); $$E.removeEvent( image,  " mousemove " this ._START ); $$E.addEvent( document,  " mousemove " this ._MOVE ); $$E.addEvent( document,  " mouseout " this ._OUT );

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

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

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

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

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

而mousemove绑定的_move移动程序,主要用来实现鼠标移动到哪里就放大哪里的功能。 为适应更多的情况(例如扩展篇的其他模式),把它绑定到document上,但也因此不能用mouseout事件来触发移出程序。 程序通过鼠标和原图的坐标比较,来判断鼠标是否移出原图对象范围:

var  x  =  e.pageX, y  =  e.pageY, rect  =   this ._rect; if  ( x  <  rect.left  ||  x  >  rect.right  ||  y  <  rect.top  ||  y  >  rect.bottom ) {      this ._END(); }  else  {     ... }

如果鼠标移出原图对象的话,就执行_END结束放大效果。

如果鼠标在原图对象上移动,就计算坐标进行定位。 先修正坐标,把鼠标坐标转化成大图的定位坐标:

pos.left  =  viewerWidth  /   2   -  ( x  -  rect.left  -   this ._repairLeft )  *  scale; pos.top  =  viewerHeight  /   2   -  ( y  -  rect.top  -   this ._repairTop )  *  scale;

再设置范围限制:

=  Math.ceil(Math.min(Math.max( pos.left, viewerWidth  -  zoom.width ),  0 )); y  =  Math.ceil(Math.min(Math.max( pos.top, viewerHeight  -  zoom.height ),  0 ));

最后设置定位,使显示框显示要放大的部位。 ps:我尝试过用scrollLeft/scrollTop来做定位,但发现这样在ie中会像锯齿那样移动,放得越大越明显,所以放弃。

【鼠标滚动缩放】

如果设置mouse属性为true,就会开启鼠标滚动缩放功能。 在执行放大效果期间,可以通过滚动鼠标滚轮对大图进行缩放处理。 其实就是根据滚轮动参数的变化来修改放大比例。

关于鼠标滚动事件,在slider中也提过,不过那时只分析了ie和ff的区别,这里再分析一下。 首先ie是用mousewheel绑定事件的,使用event的wheelDelta来获取滚动参数。 其他浏览器用以下代码测试:

代码 <! DOCTYPE html > < html xmlns = " http://www.w3.org/1999/xhtml " > < body style = " height:1000px; " > < script > function  test(e){ alert(e.type + " : " + e.detail + " _ " + e.wheelDelta) } document.addEventListener(  " DOMMouseScroll " , test,  false  ); document.addEventListener(  " mousewheel " , test,  false  ); < / script> < / body> < / html>

向下滚动一下,可以得到以下结果: ff:DOMMouseScroll:3_undefined opera:mousewheel:3_-120 chrome/safari:mousewheel:0_-120 可以看到事件的绑定,ff只支持DOMMouseScroll,其他就只支持mousewheel。 而滚动参数的获取,ff只支持detail,opera两种都支持,chrome/safari就支持wheelDelta。 ps:不明白chrome/safari的detail为什么是0,有其他用途? 而DOMMouseScroll跟mousewheel还有一个不同是前者不能直接绑定元素,后者可以。 即可以elem.onmousewheel,但不能elem.onDOMMouseScroll。

根据以上分析,在_start程序里是这样把_mouse程序绑定到document的滚动事件中:

this .mouse  &&  $$E.addEvent( document, $$B.firefox  ?   " DOMMouseScroll "  :  " mousewheel " this ._MOUSE );

在_mouse程序里面根据滚动参数和自定义的rate缩放比率得到新的放大比例:

this ._scale  +=  ( e.wheelDelta  ?  e.wheelDelta  /  ( - 120 ) : (e.detail  ||   0 /   3  )  *   this .rate;

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

var  opt  =   this .options; this ._rangeWidth  =  opt.rangeWidth; this ._rangeHeight  =  opt.rangeHeight;

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

使用技巧

【图片设置】

程序支持大图使用原图放大或用新大图。 如果用新大图而且图片比较大的话,强烈建议设置放大比例,这样程序会自动在大图载入前先使用原图放大,这样就不用等待大图加载完成。 还要注意新大图本身的宽高比例要跟原图一致,否则就对不准坐标了,使用原图放大就没有这个问题。

【显示框设置】

有两个方法可以设置显示框的尺寸: 要固定显示范围的话,先设置rangeWidth/rangeHeight,程序会根据显示范围和放大比例计算显示框的尺寸; 要用显示框当前的尺寸来显示的话,只要不设置rangeWidth/rangeHeight或设为0就可以了。

【reset】

由于各个属性和对象之间有很多的关联,很多属性不能直接修改。 程序设置了一个reset方法专门用来修改这类属性的。 如果程序加载完成后又修改了影响程序计算的样式,例如原图大小,显示框大小等,也要执行一次reset来重新设置参数和属性。

【浮动定位】

程序没有设置显示框浮动定位的功能,需要的话可以自行添加。 简单的定位可以参考实例的方法,还要小心覆盖select的问题。 如果要更复杂的浮动定位,可以参考“浮动定位提示效果”。

【opera的bug】

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

【maxthon的bug】

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

< div id = " t "  style = " width:50px; " >< / div> < script > var  t = document.getElementById( " t " ); t.clientWidth; t.style.display = " none " ; alert(t.clientWidth); < / script>

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

使用说明

实例化时,必须有一个img元素作为原图对象,和一个容器作为显示框:

var  iz  =   new  ImageZoom(  " idImage " " idViewer "  );

可选参数用来设置系统的默认属性,包括: 属性:    默认值//说明 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:销毁程序。

程序源码 

代码 var  ImageZoom  =   function (image, viewer, options) {      this ._initialize( image, viewer, options );      this ._initLoad(); }; ImageZoom.prototype  =  {    // 初始化程序   _initialize:  function (image, viewer, options) {      this ._image  =  $$(image); // 原图      this ._zoom  =  document.createElement( " img " ); // 显示图      this ._viewer  =  $$(viewer); // 显示框      this ._viewerWidth  =   0 ; // 显示框宽      this ._viewerHeight  =   0 ; // 显示框高      this ._preload  =   new  Image(); // 预载对象      this ._rect  =   null ; // 原图坐标      this ._repairLeft  =   0 ; // 显示图x坐标修正      this ._repairTop  =   0 ; // 显示图y坐标修正      this ._rangeWidth  =   0 ; // 显示范围宽度      this ._rangeHeight  =   0 ; // 显示范围高度      this ._timer  =   null ; // 计时器      this ._loaded  =   false ; // 是否加载      this ._substitute  =   false ; // 是否替换           var  opt  =   this ._setOptions(options);           this ._scale  =  opt.scale;      this ._max  =  opt.max;      this ._min  =  opt.min;      this ._originPic  =  opt.originPic;      this ._zoomPic  =  opt.zoomPic;      this ._rangeWidth  =  opt.rangeWidth;      this ._rangeHeight  =  opt.rangeHeight;           this .delay  =  opt.delay;      this .autoHide  =  opt.autoHide;      this .mouse  =  opt.mouse;      this .rate  =  opt.rate;           this .onLoad  =  opt.onLoad;      this .onStart  =  opt.onStart;      this .onMove  =  opt.onMove;      this .onEnd  =  opt.onEnd;           var  oThis  =   this , END  =   function (){ oThis._end(); };      this ._END  =   function (){ oThis._timer  =  setTimeout( END, oThis.delay ); };      this ._START  =  $$F.bindAsEventListener(  this ._start,  this  );      this ._MOVE  =  $$F.bindAsEventListener(  this ._move,  this  );      this ._MOUSE  =  $$F.bindAsEventListener(  this ._mouse,  this  );      this ._OUT  =  $$F.bindAsEventListener(  function (e){              if  (  ! e.relatedTarget )  this ._END();         },  this  );          $$CE.fireEvent(  this " init "  );   },    // 设置默认属性   _setOptions:  function (options) {      this .options  =  { // 默认值         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 // 放大结束时执行     };      return  $$.extend( this .options, options  ||  {});   },    // 初始化加载   _initLoad:  function () {      var  image  =   this ._image, originPic  =   this ._originPic,         useOrigin  =   ! this ._zoomPic  &&   this ._scale,         loadImage  =  $$F.bind( useOrigin  ?   this ._loadOriginImage :  this ._loadImage,  this  );      // 设置自动隐藏      this .autoHide  &&   this ._hide();      // 先加载原图      if  ( originPic  &&  originPic  !=  image.src ) { // 使用自定义地址         image.onload  =  loadImage;         image.src  =  originPic;     }  else   if  ( image.src ) { // 使用元素地址          if  (  ! image.complete ) { // 未载入完             image.onload  =  loadImage;         }  else  { // 已经载入             loadImage();         }     }  else  {          return ; // 没有原图地址     }      // 加载大图      if  (  ! useOrigin ) {          var  preload  =   this ._preload, zoomPic  =   this ._zoomPic  ||  image.src,             loadPreload  =  $$F.bind(  this ._loadPreload,  this  );          if  ( zoomPic  !=  preload.src ) { // 新地址重新加载             preload.onload  =  loadPreload;             preload.src  =  zoomPic;         }  else  { // 正在加载              if  (  ! preload.complete ) { // 未载入完                 preload.onload  =  loadPreload;             }  else  { // 已经载入                  this ._loadPreload();             }         }     }   },    // 原图放大加载程序   _loadOriginImage:  function () {      this ._image.onload  =   null ;      this ._zoom.src  =   this ._image.src;      this ._initLoaded();   },    // 原图加载程序   _loadImage:  function () {      this ._image.onload  =   null ;      if  (  this ._loaded ) { // 大图已经加载          this ._initLoaded();     }  else  {          this ._loaded  =   true ;          if  (  this ._scale ) { // 有自定义比例才用原图放大替换大图              this ._substitute  =   true ;              this ._zoom.src  =   this ._image.src;              this ._initLoaded();         }     }   },    // 大图预载程序   _loadPreload:  function () {      this ._preload.onload  =   null ;      this ._zoom.src  =   this ._preload.src;      if  (  this ._loaded ) { // 原图已经加载          // 没有使用替换          if  (  ! this ._substitute ) {  this ._initLoaded(); }     }  else  {          this ._loaded  =   true ;     }   },    // 初始化加载设置   _initLoaded:  function (src) {      // 初始化显示图      this ._initSize();      // 初始化显示框      this ._initViewer();      // 初始化数据      this ._initData();      // 开始执行     $$CE.fireEvent(  this " load "  );      this .onLoad();      this .start();   },    // 初始化显示图尺寸   _initSize:  function () {      var  zoom  =   this ._zoom, image  =   this ._image, scale  =   this ._scale;      if  (  ! scale ) { scale  =   this ._preload.width  /  image.width; }      this ._scale  =  scale  =  Math.min( Math.max(  this ._min, scale ),  this ._max );      // 按比例设置显示图大小     zoom.width  =  Math.ceil( image.width  *  scale );     zoom.height  =  Math.ceil( image.height  *  scale );   },    // 初始化显示框   _initViewer:  function () {      var  zoom  =   this ._zoom, viewer  =   this ._viewer;      // 设置样式      var  styles  =  { padding:  0 , overflow:  " hidden "  }, p  =  $$D.getStyle( viewer,  " position "  );      if  ( p  !=   " relative "   &&  p  !=   " absolute "  ){ styles.position  =   " relative " ; };     $$D.setStyle( viewer, styles );     zoom.style.position  =   " absolute " ;      // 插入显示图      if  (  ! $$D.contains( viewer, zoom ) ){ viewer.appendChild( zoom ); }   },    // 初始化数据   _initData:  function () {      var  zoom  =   this ._zoom, image  =   this ._image, viewer  =   this ._viewer,         scale  =   this ._scale, rangeWidth  =   this ._rangeWidth, rangeHeight  =   this ._rangeHeight;      // 原图坐标      this ._rect  =  $$D.rect( image );      // 修正参数      this ._repairLeft  =  image.clientLeft  +  parseInt($$D.getStyle( image,  " padding-left "  ));      this ._repairTop  =  image.clientTop  +  parseInt($$D.getStyle( image,  " padding-top "  ));      // 设置范围参数和显示框大小      if  ( rangeWidth  >   0   &&  rangeHeight  >   0  ) {         rangeWidth  =  Math.ceil( rangeWidth );         rangeHeight  =  Math.ceil( rangeHeight );          this ._viewerWidth  =  Math.ceil( rangeWidth  *  scale );          this ._viewerHeight  =  Math.ceil( rangeHeight  *  scale );         $$D.setStyle( viewer, {             width:  this ._viewerWidth  +   " px " ,             height:  this ._viewerHeight  +   " px "         });     }  else  {          var  styles;          if  (  ! viewer.clientWidth ) { // 隐藏              var  style  =  viewer.style;             styles  =  {                 display: style.display,                 position: style.position,                 visibility: style.visibility             };             $$D.setStyle( viewer, {                 display:  " block " , position:  " absolute " , visibility:  " hidden "             });         }          this ._viewerWidth  =  viewer.clientWidth;          this ._viewerHeight  =  viewer.clientHeight;          if  ( styles ) { $$D.setStyle( viewer, styles ); }                  rangeWidth  =  Math.ceil(  this ._viewerWidth  /  scale );         rangeHeight  =  Math.ceil(  this ._viewerHeight  /  scale );     }      this ._rangeWidth  =  rangeWidth;      this ._rangeHeight  =  rangeHeight;   },    // 开始   _start:  function () {     clearTimeout(  this ._timer );      var  viewer  =   this ._viewer, image  =   this ._image, scale  =   this ._scale;     viewer.style.display  =   " block " ;     $$CE.fireEvent(  this " start "  );      this .onStart();     $$E.removeEvent( image,  " mouseover " this ._START );     $$E.removeEvent( image,  " mousemove " this ._START );     $$E.addEvent( document,  " mousemove " this ._MOVE );     $$E.addEvent( document,  " mouseout " this ._OUT );      this .mouse  &&  $$E.addEvent( document, $$B.firefox  ?   " DOMMouseScroll "  :  " mousewheel " this ._MOUSE );   },    // 移动   _move:  function (e) {     clearTimeout(  this ._timer );      var  x  =  e.pageX, y  =  e.pageY, rect  =   this ._rect;      if  ( x  <  rect.left  ||  x  >  rect.right  ||  y  <  rect.top  ||  y  >  rect.bottom ) {          this ._END(); // 移出原图范围     }  else  {          var  pos  =  {}, scale  =   this ._scale, zoom  =   this ._zoom,             viewerWidth  =   this ._viewerWidth,             viewerHeight  =   this ._viewerHeight;          // 修正坐标         pos.left  =  viewerWidth  /   2   -  ( x  -  rect.left  -   this ._repairLeft )  *  scale;         pos.top  =  viewerHeight  /   2   -  ( y  -  rect.top  -   this ._repairTop )  *  scale;                  $$CE.fireEvent(  this " repair " , e, pos );          // 范围限制         x  =  Math.ceil(Math.min(Math.max( pos.left, viewerWidth  -  zoom.width ),  0 ));         y  =  Math.ceil(Math.min(Math.max( pos.top, viewerHeight  -  zoom.height ),  0 ));          // 设置定位         zoom.style.left  =  x  +   " px " ;         zoom.style.top  =  y  +   " px " ;                  $$CE.fireEvent(  this " move " , e, x, y );          this .onMove();     }   },    // 结束   _end:  function () {     $$CE.fireEvent(  this " end "  );      this .onEnd();      this .autoHide  &&   this ._hide();      this .stop();      this .start();   },    // 隐藏   _hide:  function () {      this ._viewer.style.display  =   " none " ;   },    // 鼠标缩放   _mouse:  function (e) {      this ._scale  +=  ( e.wheelDelta  ?  e.wheelDelta  /  ( - 120 ) : (e.detail  ||   0 /   3  )  *   this .rate;           var  opt  =   this .options;      this ._rangeWidth  =  opt.rangeWidth;      this ._rangeHeight  =  opt.rangeHeight;           this ._initSize();      this ._initData();      this ._move(e);     e.preventDefault();   },    // 开始   start:  function () {      if  (  this ._viewerWidth  &&   this ._viewerHeight ) {          var  image  =   this ._image, START  =   this ._START;         $$E.addEvent( image,  " mouseover " , START );         $$E.addEvent( image,  " mousemove " , START );     }   },    // 停止   stop:  function () {     clearTimeout(  this ._timer );     $$E.removeEvent(  this ._image,  " mouseover " this ._START );     $$E.removeEvent(  this ._image,  " mousemove " this ._START );     $$E.removeEvent( document,  " mousemove " this ._MOVE );     $$E.removeEvent( document,  " mouseout " this ._OUT );     $$E.removeEvent( document, $$B.firefox  ?   " DOMMouseScroll "  :  " mousewheel " this ._MOUSE );   },    // 修改设置   reset:  function (options) {      this .stop();           var  viewer  =   this ._viewer, zoom  =   this ._zoom;      if  ( $$D.contains( viewer, zoom ) ) { viewer.removeChild( zoom ); }           var  opt  =  $$.extend(  this .options, options  ||  {} );      this ._scale  =  opt.scale;      this ._max  =  opt.max;      this ._min  =  opt.min;      this ._originPic  =  opt.originPic;      this ._zoomPic  =  opt.zoomPic;      this ._rangeWidth  =  opt.rangeWidth;      this ._rangeHeight  =  opt.rangeHeight;           // 重置属性      this ._loaded  =   this ._substitute  =   false ;      this ._rect  =   null ;      this ._repairLeft  =   this ._repairTop  =        this ._viewerWidth  =   this ._viewerHeight  =   0 ;           this ._initLoad();   },    // 销毁程序   dispose:  function () {     $$CE.fireEvent(  this " dispose "  );      this .stop();      if  ( $$D.contains(  this ._viewer,  this ._zoom ) ) {          this ._viewer.removeChild(  this ._zoom );     }      this ._image.onload  =   this ._preload.onload  =          this ._image  =   this ._preload  =   this ._zoom  =   this ._viewer  =          this .onLoad  =   this .onStart  =   this .onMove  =   this .onEnd  =          this ._START  =   this ._MOVE  =   this ._END  =   this ._OUT  =   null   } }

 

完整实例下载

转载于:https://www.cnblogs.com/cloudgamer/archive/2010/04/01/ImageZoom.html

相关资源:ImageZoom 图片放大镜效果(多功能扩展篇)
最新回复(0)