功能说明:
在淘宝,京东之类的电子商务网站一般会有商品放大浏览功能,帮助顾客分析产品质量,这次的放大器程序正是模仿了这种效果,并支持如下功能:
1.图片局部放大。
2.鼠标滚轮调整放大倍数。
支持IE6 7 8 firefox chrome
效果预览:
实现原理:这次的图片放大器实现简单来说就是:分层+裁剪
分层:
在原图区域,图片被分成三层:
1.原图层:就是一开始看到的图片。
2.透明遮罩层:原图层上面的半透明层,用于产生遮罩效果。
3.手柄区域层:就是跟随鼠标移动的手柄区域,手柄区域内容在右边被放大。
裁剪:
裁剪主要用在两个地方,一个是对原图中手柄区域层的裁剪,一个是放大区域对大图的裁剪。
代码分析:
首先有必要先看看传入的参数:
imgElem:原图对象。
tims:默认缩放倍数。
windowSize:显示窗口大小。
winLeft,winTop,imgLeft,imgTop分别为显示窗口和原图的位置参数。
imgElm2.src = bigImg.src = imgElem.src;
imgElm2.onload = function() {
setImgsAndDivStyle(imgElem, imgElm2, opacityDiv, bigImg);
document.body.appendChild(bigImg);
container.appendChild(opacityDiv);
container.appendChild(imgElm2);
}
}
这里分别设置三层(原图层,透明层,手柄层)的样式,并且需要注意的是,要在图片加载完后才开始后面设置样式的操作,否则会造成后面的操作出现问题。
bigImg.style.clip = 'rect(' + parseInt(rect.top) * times + 'px ' + parseInt(rect.right) * times + 'px ' + parseInt(rect.bottom) * times + 'px ' + parseInt(rect.left) * times + 'px)';
bigImg.style.top = winTop - parseInt(rect.top) * times + 'px';
bigImg.style.left = winLeft - parseInt(rect.left) * times + 'px'; }
设置大图剪裁区域的函数,上面说过,放大效果的实现其实就是把一幅大图通过剪裁,然后再根据鼠标坐标定位的过程。注意要乘上默认的放大倍数times。
imgElem.style.clip = 'rect(' + rect.top + ' ' + rect.right + ' ' + rect.bottom + ' ' + rect.left + ')';
}
然后是设置手柄层图像剪裁区域的函数,除了放大效果依赖于剪裁外,跟随手柄移动的图像层也通过剪裁实现,差别只是大图在剪裁后需要重新设置left和top的值,手柄区域剪裁后并不需要重新定位。
eve = eve || window.event;
tar = eve.target || eve.srcElement;
if (tar == imgElem || tar == opacityDiv) {
rec = new Rect(parseInt(eve.clientX) - halfWidth - imgLeft, parseInt(eve.clientY) - halfHight - imgTop - container.offsetTop, parseInt(Handler.style.width));
setImgRect(rec);
bigImg.style.display = 'block';
setBigImgRect(rec);
}
}
对鼠标移动事件的处理程序绑定。鼠标移动过程中,根据鼠标的坐标,重新剪裁手柄区域图片和大图,产生图像跟随鼠标移动以及在右边放大的效果。注意这里因为是为document注册事件处理程序,所以要判断target是否为图像对象。
document.onmousewheel = resize;
}
else {
document.addEventListener("DOMMouseScroll", resize, false);
}
/* reset the style of images and handler */
function resize(eve) {
eve = eve || window.event;
if (navigator.userAgent.indexOf("Firefox") > 0) {
times += eve.detail / 3;
}
else
times += eve.wheelDelta / 120;
firefox和非firefox对鼠标滚动事件的处理都不同,因此需要检测后分别处理。关于这个知识点详细可见这里:http://www.javascriptkit.com/javatutors/onmousewheel.shtml
eve = eve || window.event;
if (navigator.userAgent.indexOf("Firefox") > 0) {
times += eve.detail / 3;
}
else
times += eve.wheelDelta / 120;
times = Math.min(Math.max(0.8, times), 15); //the max time is 15,and the min time is 0.8
bigImg.style.width = parseInt(imgElem.clientWidth) * times + 'px';
bigImg.style.height = parseInt(imgElem.clientHeight) * times + 'px';
Handler.style.height = Handler.style.width = windowSize / times + 'px';
halfWidth = parseInt(Handler.style.width) / 2;
halfHight = parseInt(Handler.style.height) / 2;
rec = new Rect(parseInt(eve.clientX) - halfWidth - imgLeft, parseInt(eve.clientY) - halfHight - imgTop, parseInt(Handler.style.width));
setImgRect(rec);
setBigImgRect(rec);
if (!window.event)
eve.preventDefault();
return false;
}
}
mousewheel的事件处理程序中,通过鼠标滚动设置放大倍数,这里使用max和min函数来限制放大的最大和最小倍数(注意在平时很多时候都会遇到使用max和min函数搭配规定数值范围的情况)。此外,重置大图的样式,包括:高度,宽度,并且重新设置裁剪区域。另外需要注意的是,firefox需要通过preventDefault来禁止滑轮滚动默认行为,以防滚动条发生滚动。(IE下则是用后面的return false)。
this.left = left + 'px';
this.top = top + 'px';
this.right = parseInt(this.left) + width + 'px';
this.bottom = parseInt(this.top) + width + 'px';
}
最后这个是一个裁剪区域对象的构造函数。正如前面所说,由于手柄层和大图层都需要用到图片裁剪,因此这里把图片裁剪需要用到的参数封装在一个裁剪对象的构造函数里,每次通过初始化不同裁剪对象,传入不同的裁剪函数,实现不同的裁剪操作。