@greenfavo
2015-11-30T13:15:59.000000Z
字数 2352
阅读 1138
html5
在天猫淘宝购物时点开商品详情页把鼠标放到商品图片上移动时,就可以查看商品细节,这就是一个局部放大镜的功能。用canvas可以轻松实现这种功能。
之前在慕课网上看的canvas视频上介绍了这种局部放大镜的实现方法,采用了离屏canvas技术。其实就是先在DOM中创建2个canvas,准备一张大图,通过drawImage()方法,把大图缩放成小图放到其中一个canvas中,在另一个canvas里放这张大图,是实际尺寸。把大图隐藏。当鼠标在小图上移动时,就把大图上的像素复制到放大镜上。放大系数就是大图与小图宽度之比。放大的像素只显示在放大镜里,因此要用clip()方法裁剪。
这里用到的API在我上篇文章canvas API详解中有详细介绍。就不多说了。功能很简单,直接上代码吧。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>canvas局部放大镜</title>
<style type="text/css">
#canvas{
margin: 30px auto;
/*设置了block才会居中*/
display: block;
}
#offcanvas{
display: none;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<!-- 离屏canvas -->
<canvas id="offcanvas"></canvas>
<script>
var canvas=document.getElementById('canvas');
var context=canvas.getContext('2d');
var offcanvas=document.getElementById('offcanvas');
var offcontext=offcanvas.getContext('2d');
var image=new Image();
var scale;//放大系数
canvas.width=500;
canvas.height=300;
image.src='images/4.jpg';
image.onload=function(){
offcanvas.width=image.width;
offcanvas.height=image.height;
scale=offcanvas.width/canvas.width;
context.drawImage(image,0,0,canvas.width,canvas.height);//不是图片的实际大小,缩放了
offcontext.drawImage(image,0,0);//是图片的实际大小
}
canvas.onmousemove=function(e){
var point=window_to_canvas(e.clientX,e.clientY);
//只有小图才调用放大镜
if (canvas.width<offcanvas.width) {
show_big_pic(point);
canvas.style.cursor='move';
};
}
canvas.onmouseout=function(){
context.clearRect(0,0,canvas.width,canvas.height);
context.drawImage(image,0,0,canvas.width,canvas.height);
}
function show_big_pic(point){
//清空画布,重新绘制
context.clearRect(0,0,canvas.width,canvas.height);
context.drawImage(image,0,0,canvas.width,canvas.height);
var imgLG_cx=point.x*scale;//大图中心位置
var imgLG_cy=point.y*scale;
var mr=100;//放大镜半径
var sx=imgLG_cx-mr;//源图像起始坐标
var sy=imgLG_cy-mr;
var dx=point.x-mr;//目标图像起始坐标
var dy=point.y-mr;
context.save();
context.lineWidth=5;
context.strokeStyle="#ccc";
context.beginPath();
context.arc(point.x,point.y,mr,0,2*Math.PI);//绘制圆形放大镜
context.stroke();
context.clip();//剪辑,只在该区域显示
context.drawImage(offcanvas,sx,sy,2*mr,2*mr,dx,dy,2*mr,2*mr);
context.restore();
}
//鼠标在画布内的距离
function window_to_canvas(x,y){
var box=canvas.getBoundingClientRect();
return{x:x-box.left,y:y-box.top};
}
</script>
</body>
</html>
当canvas里的图片比图片实际尺寸大时,如果不判断就直接调用放大镜,并不会显示很圆润的放大效果,而是会产生一种从源图像抽离出来的效果。所以应该判断下是否是小图,小图才放大。
每次鼠标移动都是重新将大图中适当位置里的像素复制到放大镜上,所以每次调用放大镜都应该清空放大镜里面的内容,不然内容会重叠。但放大镜每次移动的位置都不一样,不好判断,所以直接把整个画布清空就好了,这时应该重绘小图。