支持使用原图放大或新图片设置大图【www.602.net】

一般用于放大查看商品图片,在凡客,京东商城,阿里巴巴等都有类似的效果。
好处是能在原图附近对图片进行局部放大查看,而且可以通过鼠标控制查看的部位。
前一阵子看到sohighthesky的图片放大效果,心血来潮自己也写一个看看。
这个程序有以下特点: 1,支持使用原图放大或新图片设置大图;
2,大图完成载入前使用原图放大代替,减少操作等待时间;
3,支持鼠标滚动缩放大图;
4,可以通过设置显示范围或显示框大小设置显示尺寸;
5,可以设置是否自动隐藏显示框; 6,支持插件形式的扩展来实现更多的功能。
兼容:ie6/7/8, firefox 3.6.2, opera 10.51, safari 4.0.4, chrome 4.1
复制代码 代码如下: 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 { $$D.setStyle; }
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{ if this._www.602.net,END;
当鼠标移出document会触发mouseout,如果当前relatedTarget是null的话,就延时执行_end结束程序:
var oThis = this, END = function; }; this._END = function(){
oThis._timer = setTimeout; };
在_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结束放大效果。
如果鼠标在原图对象上移动,就计算坐标,并通过_repair程序把坐标转化成定位需要的值。
最后设置大图的left/top定位使显示框显示要放大的部位。
ps:我尝试过用scrollLeft/scrollTop来做定位,但发现这样在ie中会像锯齿那样移动,放得越大越明显,所以放弃。
如果设置mouse属性为true,就会开启鼠标滚动缩放功能。
在执行放大效果期间,可以通过滚动鼠标滚轮对大图进行缩放处理。
其实就是根据滚轮动参数的变化来修改放大比例。
关于鼠标滚动事件,在slider中也提过,不过那时只分析了ie和ff的区别,这里再分析一下。
首先ie是用mousewheel绑定事件的,使用event的wheelDelta来获取滚动参数。
其他浏览器用以下代码测试: 复制代码
代码如下:

向下滚动一下,可以得到以下结果: 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 / : * 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来重新设置参数和属性。
程序没有设置显示框浮动定位的功能,需要的话可以自行添加。
简单的定位可以参考实例的方法,还要小心覆盖select的问题。
如果要更复杂的浮动定位,可以参考“浮动定位提示效果”。 测试中发现opera
10.10有两个bug。
分别是img元素设置透明时会看到背景图,用js修改鼠标样式会有问题。
不过这两个问题在10.50都已经修复了,还没升级的赶快升啦。 用maxthon
2.5.1测试时发现一个问题,测试以下代码: 复制代码 代码如下:

一般来说用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:销毁程序。 程序源码 复制代码 代码如下: var ImageZoom =
function(image, viewer, options) { this._initialize( image, viewer,
options ); this._initMode; this._oninit; }; ImageZoom.prototype = {
//初始化程序 _initialize: function(image, viewer, options) {
this._image = $$;//原图 this._zoom = document.createElement;//显示图
this._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; 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; }; this._END = function(){
oThis._timer = setTimeout; }; this._START = $$F.bindAsEventListener;
this._MOVE = $$F.bindAsEventListener; this._MOUSE =
$$F.bindAsEventListener; this._OUT = $$F.bindAsEventListener{ if
this._END; }, //设置默认属性 _setOptions: function { this.options =
{//默认值 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//放大结束时执行 }; return $$.extend(this.options,
options || {}); }, //根据模式初始化函数属性 _initMode: function { mode
= $$.extend({ options:{}, init: $$.emptyFunction, load:
$$.emptyFunction, start: $$.emptyFunction, end: $$.emptyFunction, move:
$$.emptyFunction, dispose:$$.emptyFunction }, (ImageZoom._MODE || {})[
mode.toLowerCase; this.options = $$.extend( mode.options, this.options
); this._oninit = mode.init; this._onload = mode.load; this._onstart
= mode.start; this._onend = mode.end; this._onmove = mode.move;
this._ondispose = mode.dispose; }, //初始化加载 _initLoad: function()
{ var image = this._image, originPic = this._originPic, useOrigin =
!this._zoomPic && this._scale, loadImage = $$F.bind( useOrigin ?
this._loadOriginImage : this._loadImage, this ); //设置自动隐藏 if {
this._viewer.style.display = “none”; } //先加载原图 if ( originPic &&
originPic != image.src ) {//使用自定义地址 image.onload = loadImage;
image.src = originPic; } else if {//使用元素地址 if {//未载入完
image.onload = loadImage; } else {//已经载入 loadImage(); } } else {
return;//没有原图地址 } //加载大图 if { 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.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._initLoaded(); } else { this._loaded = true; if
{//有自定义比例才用原图放大替换大图 this._substitute = true;
this._zoom.src = this._image.src; this._initLoaded(); } } },
//大图预载程序 _loadPreload: function() { this._preload.onload = null;
this._zoom.src = this._preload.src; if {//原图已经加载 //没有使用替换
if { this._initLoaded(); } } else { this._loaded = true; } },
//初始化加载设置 _initLoaded: function { //初始化显示图
this._initSize(); //初始化显示框 this._initViewer(); //初始化数据
this._initData(); //开始执行 this._onload; this.start(); },
//初始化显示图尺寸 _initSize: function() { var zoom = this._zoom,
image = this._image, scale = this._scale; if { scale =
this._preload.width / image.width; } this._scale = scale = Math.min(
Math.max, 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; if ( p != “relative” && p != “absolute” ){
styles.position = “relative”; }; $$D.setStyle; zoom.style.position =
“absolute”; //插入显示图 if ( !$$D.contains{ viewer.appendChild; } },
//初始化数据 _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; //修正参数 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; rangeHeight = Math.ceil; this._viewerWidth
    = Math.ceil; 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 {
    $$D.setStyle; } rangeWidth = Math.ceil( this._viewerWidth / scale );
    rangeHeight = Math.ceil( this._viewerHeight / scale ); }
    this._rangeWidth = rangeWidth; this._rangeHeight = rangeHeight; },
    //开始 _start: function() { clearTimeout; var viewer = this._viewer,
    image = this._image, scale = this._scale; viewer.style.display =
    “block”; 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 { clearTimeout; 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 zoom = this._zoom, pos = this._repair( x – rect.left –
    this._repairLeft, y – rect.top – this._repairTop ); this._onmove;
    //设置定位 zoom.style.left = pos.left + “px”; zoom.style.top = pos.top +
    “px”; this.onMove(); } }, //修正坐标 _repair: function { var scale =
    this._scale, zoom = this._zoom, viewerWidth = this._viewerWidth,
    viewerHeight = this._viewerHeight; //修正坐标 x = Math.ceil(
    viewerWidth / 2 – x * scale ); y = Math.ceil( viewerHeight / 2 – y *
    scale ); //范围限制 x = Math.min( Math.max( x, viewerWidth – zoom.width
    ), 0 ); y = Math.min( Math.max( y, viewerHeight – zoom.height ), 0 );
    return { left: x, top: y }; }, //结束 _end: function; this.onEnd(); if
    { this._viewer.style.display = “none”; } this.stop; }, //鼠标缩放
    _mouse: function { this._scale += ( e.wheelDelta ? e.wheelDelta / : *
    this.rate; var opt = this.options; this._rangeWidth = opt.rangeWidth;
    this._rangeHeight = opt.rangeHeight; this._initSize; this._move;
    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; $$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 { this.stop(); var viewer = this._viewer,
    zoom = this._zoom; if ( $$D.contains { viewer.removeChild; } 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; this.stop(); if ( $$D.contains( this._viewer, this._zoom ) )
    { this._viewer.removeChild; } 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 } }
    转载请注明出处:
    如有任何建议或疑问,欢迎留言讨论。打包下载地址

发表评论

电子邮件地址不会被公开。 必填项已用*标注