淘宝首页装饰宝贝图片时鼠标变大了怎么办?

这种效果也叫放大镜效果,最开始好像是在ppg里面出现的,后来很多模仿的都出来了。

一般用于放大查看商品图片,在JD.COM商城、柯凡、阿里巴巴都有类似的效果。

好处是可以在原图附近局部放大查看图片,可以用鼠标控制查看位置。

基本原理

首先,必须有一个img元素作为原始对象,一个容器作为显示框。

在显示框中再放一个img元素作为大图对象,根据比例设置大小。

当鼠标在原图上移动时,通过大图的绝对定位来显示相应的部分,实现了类似放大镜的效果。

图片加载

程序初始化时会先执行_initLoad程序,主要用来加载图片。

因为加载前img得到的尺寸不准确,所以相关参数的计算要等到图片加载后。

放大有两种方式:用原图像放大,用放大后的新图像。

放大原图的好处是只需要加载一张图片,使用新的图片可以获得更清晰的效果。

根据不同的方法,会选择相应的原始加载器:

useOrigin =!这个。_ zoomPic & amp& amp这个。_scale,

loadImage = $$F.bind( useOrigin?这个。_loadOriginImage:这个。_loadImage,this);

当未设置大图像但有放大倍率时,将自动使用原始图像放大加载器。

我们来看看用原图放大加载的过程:

1,加载原图:

if(origin pic & amp;& amporiginPic!= image.src ) {

image.onload = loadImage

image.src = originPic

} else if ( image.src ) {

如果(!image.complete ) {

image.onload = loadImage

}否则{

loadImage();

}

}否则{

返回;

}

_originPic属性记录原始图像的地址。如果原始图像已设置,并且不同于元素的当前加载图像,则设置onload并加载原始图像。

否则,如果该元素当前有加载的图片,先通过complete判断加载是否完成,设置onload不停止。如果完成,直接执行加载程序。

最后,如果没有原图,退出程序。

2.执行_loadOriginImage加载程序:

这个。_ image.onload = null

这个。_zoom.src = this。_ image.src

这个。_ init loaded();

因为ie6/7的gif图片加载有bug,所以会先重置onload。

然后execute _initLoaded初始化负载设置程序。

使用新图片有点复杂:

1,加载原图,如上。

2.预装大图:

var preload = this。_preload,zoomPic = this。_zoomPic || image.src,

loadPreload = $$F.bind( this。_loadPreload,this);

如果(zoomPic!= preload.src ) {

preload.onload = loadPreload

preload.src = zoomPic

}否则{

如果(!preload.complete ) {

preload.onload = loadPreload

}否则{

这个。_ load preload();

}

}

_preload是一个预加载对象,使用_loadPreload预加载器。

预装对象主要是用来获取大图的原始尺寸,也是后面原图替换技能的基础。

如果没有大图,说明目前没有大图,没有放大,所以用原图做大图。

加载方式和原图差不多。

3.加载原始图像后,执行_loadImage原始图像加载程序:

复制代码

如果(这个。_loaded ) {

这个。_ init loaded();

}否则{

这个。_ loaded = true

如果(这个。_scale ) {

这个。_ substitute = true

这个。_zoom.src = this。_ image.src

这个。_ init loaded();

}

}

复制代码

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

否则,将_loaded设置为true,以标记原始图像已经加载。如果此时有自定义比例,先用原图替换大图。

因为大图加载通常比较慢,所以可以通过先替换原图来立即操作,将_substitute属性设置为true标志使用替换。

4.完成大图预加载后,执行_loadPreload大图预加载程序:

这个。_zoom.src = this。_ preload.src

如果(这个。_loaded ) {

如果(!这个。_substitute ) {这个。_ init loaded();}

}否则{

这个。_ loaded = true

}

如果_loaded为true,则表示原映像已经加载,如果_substitute为false,即原映像没有被替换,则执行_initLoaded程序。

如果原始图像没有完全加载,将_loaded设置为true以标记大图像已经加载。

关于图像加载的另一个问题,测试下面的代码:

复制代码

& lt脚本& gt

var img =新图像

功能测试(){

img . onload = function(){ alert(" load ")}

img.src= "。hk/images/nav_logo8.png "

}

测试()

设置超时(测试,3000)

& lt/script & gt;

复制代码

在chrome/safari中,“加载”只会弹出一次,其他都正常两次,可能是优化了什么的。

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

负载设置

初始化加载设置程序in _initLoaded,主要是为触发放大效果做准备。

步骤1,执行_initSize程序初始化显示尺寸。

首先,校正放大比例:

如果(!scale ) { scale =这个。_ preload . width/image . width;}

这个。_ scale = scale = math . min(math . max(this。_min,scale),这个。_ max);

如果未设置比例,则从预加载的对象中获得的默认尺寸将作为大图形尺寸。

加载图片时采取了“安全措施”,以确保在此处可以获得放大倍率。

您还可以通过自定义最大值和最小值属性来限制比例大小。

然后你可以按比例设置大图的大小:

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 ");

如果(p!= "亲戚" & amp& ampp!= " absolute "){ styles . position = " relative ";};

$$D.setStyle(查看器,样式);

zoom . style . position = " absolute ";

然后将显示图插入显示框:

如果(!$$D.contains( viewer,zoom)){ viewer . appendchild(zoom);}

第三步是执行_initData初始化数据程序,主要是设置一些放大时使用的参数。

包括用于位置判断的原始坐标:

这个。_ rect = $ $ d . rect(image);

左侧/顶部校正的校正参数:

这个。_ repair left = image . client left+parse int($ $ d . get style(image," padding-left "));

这个。_ repair top = image . client top+parse int($ $ d . get style(image," padding-top));

还有范围参数和显示大小。

range参数是原始图像中要显示的范围的大小,display size是显示帧的显示大小。

如果范围参数由rangeWidth和rangeHeight定制,则可以通过组合放大比率来计算显示尺寸:

range width = math . ceil(range width);

range height = math . ceil(range height);

这个。_ viewer width = math . ceil(range width * scale);

这个。_ viewer height = math . ceil(range height * scale);

$$D.setStyle(查看器,{

宽度:这个。_viewerWidth + "px ",

身高:这个。_viewerHeight + "px "

});

复制代码

如果未设置,将使用显示框的默认显示大小:

复制代码

var风格;

如果(!viewer.clientWidth ) {

var style = viewer.style

样式= {

显示:style.display,

位置:style.position,

可视性:样式.可视性

};

$$D.setStyle(查看器,{

显示:“阻挡”,位置:“绝对”,可见性:“隐藏”

});

}

这个。_ viewer width = viewer . client width;

这个。_ viewer height = viewer . client height;

if ( styles ) { $$D.setStyle(查看器,样式);}

rangeWidth = Math.ceil( this。_ viewer width/scale);

rangeHeight = Math.ceil( this。_ viewer height/scale);

复制代码

注意,显示范围是通过clientWidth/clientHeight获得的。

如果显示框处于隐藏状态,显示为none,则不能直接获取clientWidth/clientHeight。

在这种情况下,程序使用以下方法来获取:

1,记录显示/位置/可见度的原始值;

2,分别设置为“块”/“绝对”/“隐藏”,可以隐藏也可以占用;

3、获取参数;

4、复位原值,恢复原始状态。

得到显示范围后,匹配比例就可以得到范围参数。

Ps:这是一种通用的获取非占用元素大小参数的方法,jquery的css也使用这种方法获取宽度/高度。

按比例计算后,可能会得到小数,但大小只能是整数,程序总是用Math.ceil来取整。

放大效应

设置好一切后,您可以执行开始设置触发器。

程序会自动执行start方法,主要是将_start程序绑定到原始图像对象的mouseover/mousemove上:

var image = this。_image,START = this。_ START

$$E.addEvent( image," mouseover ",START);

$$E.addEvent( image," mousemove ",START);

对应于移入原始对象和在原始对象上移动的情况。

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

bound _start程序主要用于解除绑定和绑定一些事件:

密码

为了在移出窗口时结束放大效果,将_OUT程序绑定到mouseout of document:

这个。_OUT = $$F.bindAsEventListener(函数(e){

如果(!e.relatedTarget)这个。_ END();

},这个);

当鼠标移出文档时,会触发mouseout。如果当前relatedTarget为空,将延迟执行_end来结束程序:

var oThis = this,END = function(){ oThis。_ end();};

这个。_END = function(){ oThis。_timer = setTimeout( END,othis . delay);};

在_end程序中,将首先执行stop方法来删除所有可能的绑定事件,然后执行start方法来继续等待触发器。

mousemove绑定的_move移动程序主要用于鼠标移动到哪里就放大到哪里。

为了适应更多的情况(比如扩展的其他模式),它被绑定到文档,但因此mouseout事件不能用来触发移除程序。

程序比较鼠标和原始图像的坐标,判断鼠标是否移出原始图像对象范围:

var x = e.pageX,y = e.pageY,rect = this。_ rect

if(x & lt;rect.left | | x & gtrect.right | | y & ltrect.top | | y & gtrect.bottom ) {

这个。_ END();

}否则{

...

}

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

如果鼠标在原始对象上移动,将计算坐标以进行定位。

首先修正坐标,将鼠标坐标转换成大图的定位坐标:

pos . left = viewer width/2-(x-rect . left-this。_ repair left)* scale;

pos . top = viewer height/2-(y-rect . top-this。_repairTop ) *比例;

再次设置范围限制:

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));

最后,设置定位,使显示框显示要放大的部分。

Ps:我尝试过用scrollLeft/scrollTop定位,但是发现在ie里会像锯齿一样移动,而且越大越明显,所以放弃了。

鼠标滚动和缩放

如果mouse属性设置为true,将打开鼠标滚动和缩放功能。

在放大效果期间,您可以通过滚动鼠标滚轮来放大大图。

其实就是根据压路机动力学参数的变化来修改放大倍数。

关于鼠标滚动事件,slider里也有提到,但当时只分析了ie和ff的区别。这里再来分析一下。

首先,ie使用mousewheel绑定事件,使用事件的wheelDelta获取滚动参数。

其他浏览器使用以下代码进行测试:

密码

向下滚动,可以得到以下结果:

ff:DOMMouseScroll:3_undefined

歌剧:鼠标滚轮:3_-120

chrome/safari:鼠标滚轮:0_-120

可以看到事件的绑定,ff只支持DOMMouseScroll,其他只支持mousewheel。

至于滚动参数的获取,ff只支持detail和opera,chrome/safari支持wheelDelta。

Ps:不明白为什么chrome/safari的细节是0,还有其他用途。

DOMMouseScroll和mousewheel的另一个区别是,前者不能直接绑定元素,而后者可以。

也就是说,你可以elem.onmousewheel,但是不能elem.onDOMMouseScroll。

根据以上分析,在_start程序中,_mouse程序与文档的滚动事件绑定如下:

这只老鼠& amp& amp$$E.addEvent(文档,$$B.firefox?" dommousscroll ":" mouse wheel ",这个。_ MOUSE);

在_mouse程序中,根据滚动参数和用户自定义的缩放比率获得新的缩放比率:

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

修改比例时,程序参数也需要重新计算。

由于_rangeWidth/_rangeHeight会影响计算过程,因此有必要恢复到用户定义的默认值:

var opt = this.options

这个。_ range width = opt . range width;

这个。_ range height = opt . range height;

然后执行_initSize和_initData重置大小和参数,然后执行_move重定位。

最后,记得使用preventDefault来防止触发页面滚动。