[关闭]
@greenfavo 2015-11-30T13:15:59.000000Z 字数 2352 阅读 1138

canvas局部放大镜

html5
在天猫淘宝购物时点开商品详情页把鼠标放到商品图片上移动时,就可以查看商品细节,这就是一个局部放大镜的功能。用canvas可以轻松实现这种功能。

原理分析

之前在慕课网上看的canvas视频上介绍了这种局部放大镜的实现方法,采用了离屏canvas技术。其实就是先在DOM中创建2个canvas,准备一张大图,通过drawImage()方法,把大图缩放成小图放到其中一个canvas中,在另一个canvas里放这张大图,是实际尺寸。把大图隐藏。当鼠标在小图上移动时,就把大图上的像素复制到放大镜上。放大系数就是大图与小图宽度之比。放大的像素只显示在放大镜里,因此要用clip()方法裁剪。

这里用到的API在我上篇文章canvas API详解中有详细介绍。就不多说了。功能很简单,直接上代码吧。

实现

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>canvas局部放大镜</title>
  6. <style type="text/css">
  7. #canvas{
  8. margin: 30px auto;
  9. /*设置了block才会居中*/
  10. display: block;
  11. }
  12. #offcanvas{
  13. display: none;
  14. }
  15. </style>
  16. </head>
  17. <body>
  18. <canvas id="canvas"></canvas>
  19. <!-- 离屏canvas -->
  20. <canvas id="offcanvas"></canvas>
  21. <script>
  22. var canvas=document.getElementById('canvas');
  23. var context=canvas.getContext('2d');
  24. var offcanvas=document.getElementById('offcanvas');
  25. var offcontext=offcanvas.getContext('2d');
  26. var image=new Image();
  27. var scale;//放大系数
  28. canvas.width=500;
  29. canvas.height=300;
  30. image.src='images/4.jpg';
  31. image.onload=function(){
  32. offcanvas.width=image.width;
  33. offcanvas.height=image.height;
  34. scale=offcanvas.width/canvas.width;
  35. context.drawImage(image,0,0,canvas.width,canvas.height);//不是图片的实际大小,缩放了
  36. offcontext.drawImage(image,0,0);//是图片的实际大小
  37. }
  38. canvas.onmousemove=function(e){
  39. var point=window_to_canvas(e.clientX,e.clientY);
  40. //只有小图才调用放大镜
  41. if (canvas.width<offcanvas.width) {
  42. show_big_pic(point);
  43. canvas.style.cursor='move';
  44. };
  45. }
  46. canvas.onmouseout=function(){
  47. context.clearRect(0,0,canvas.width,canvas.height);
  48. context.drawImage(image,0,0,canvas.width,canvas.height);
  49. }
  50. function show_big_pic(point){
  51. //清空画布,重新绘制
  52. context.clearRect(0,0,canvas.width,canvas.height);
  53. context.drawImage(image,0,0,canvas.width,canvas.height);
  54. var imgLG_cx=point.x*scale;//大图中心位置
  55. var imgLG_cy=point.y*scale;
  56. var mr=100;//放大镜半径
  57. var sx=imgLG_cx-mr;//源图像起始坐标
  58. var sy=imgLG_cy-mr;
  59. var dx=point.x-mr;//目标图像起始坐标
  60. var dy=point.y-mr;
  61. context.save();
  62. context.lineWidth=5;
  63. context.strokeStyle="#ccc";
  64. context.beginPath();
  65. context.arc(point.x,point.y,mr,0,2*Math.PI);//绘制圆形放大镜
  66. context.stroke();
  67. context.clip();//剪辑,只在该区域显示
  68. context.drawImage(offcanvas,sx,sy,2*mr,2*mr,dx,dy,2*mr,2*mr);
  69. context.restore();
  70. }
  71. //鼠标在画布内的距离
  72. function window_to_canvas(x,y){
  73. var box=canvas.getBoundingClientRect();
  74. return{x:x-box.left,y:y-box.top};
  75. }
  76. </script>
  77. </body>
  78. </html>

注意

当canvas里的图片比图片实际尺寸大时,如果不判断就直接调用放大镜,并不会显示很圆润的放大效果,而是会产生一种从源图像抽离出来的效果。所以应该判断下是否是小图,小图才放大。

每次鼠标移动都是重新将大图中适当位置里的像素复制到放大镜上,所以每次调用放大镜都应该清空放大镜里面的内容,不然内容会重叠。但放大镜每次移动的位置都不一样,不好判断,所以直接把整个画布清空就好了,这时应该重绘小图。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注