• Canvas实现放大镜效果完整案例分析(附代码)


    本文主要记录 canvas 在图像、文字处理、离屏技术和放大镜特效的实现过程中使用到的API。先看下效果吧:
    一张模糊的图片:

    鼠标点击任意位置,产生放大效果:

    哇塞~ 一个帅哥,哈哈哈哈~

    1、放大镜原理

    实现效果:如上图,点击或点击滑动鼠标显示一个区域,区域中显示对应点击部分范围的放大清晰图片。那么问题就可以肢解为3部分:

    1、如何在canvas(模糊图)上再画出另外一个canvas(清晰放大图);
    2、如何将canvas中显示的(清晰放大图)剪切出圆形区域。
    3、如何在鼠标点击滑动的时候显示该区域;
    

    2、显示模糊照片

    其实一般的交互不是模糊照片,这里我只是为了夸张下效果,用了张模糊的原图,哈哈哈,canvas本身是可以对清晰的图片做滤镜处理,涉及到很多图形学的算法,然后我不会,默默的打开了PS手动高斯模糊了一张照片...嗯,没毛病!
    首先定义一个canvas元素

      <canvas id="canvas"></canvas>
    
    //定义canvas画布
    var canvas1 = document.getElementById('canvas1');
        ctx1 = canvas.getContext('2d');
    
    //模糊图片加载
    var image1 = new Image();
    image1.src = "./模糊.png";
    
    //图片加载成功后绘制图片
    image1.onload = function() {
      //drawImage 在画布上绘制模糊图片
      ctx1.drawImage(image1, 0, 0, canvas1.width, canvas1.height);
    };     
    

    ctx1.drawImage(图片,x位置,y位置,图片显示宽度,图片显示高度)

    3、加载清晰图片

    我们再加一个canvas(放大镜看到的图片),初始隐藏:

    <canvas id="canvas2" style="display:none"></canvas>
    
    var canvas2 = document.getElementById('canvas2'),
        ctx2 = canvas2.getContext('2d'),
        scale = 2; // 放大倍数
    
    // canvas2的图片大小是模糊图片的2倍
    canvas2.width = canvas.width * scale;
    canvas2.height = canvas.height * scale;
    
    // 在canvas2中加载图片
    var image2 = new Image();
    image2.src = "name2.png";
    
    image2.onload = function() {
      ctx2.drawImage(image2, 0, 0, canvas2.width, canvas2.height);
    };
    

    4、显示放大镜

    4.1 绘制放大镜

    鼠标所处的位置点(x,y)是区域的中心,计算出清晰图所在的位置点,截取圆形

    // 保存当前状态
    ctx1.save();
    // 边框
    ctx1.strokeStyle = "#9eddf1";
    ctx1.lineWidth = 3;
    // 开始绘制
    ctx1.beginPath();
    // ⚪
    ctx1.arc(x, y, mr, 0, Math.PI * 2);
    ctx1.stroke();
    // 表示剪切
    ctx1.clip();
    
    // 画图
    ctx1.drawImage(that.canvas2, sx, sy, 2 * mr, 2 * mr, dx, dy, 2 * mr, 2 * mr);
    
    // 释放当前状态
    ctx1.restore();
    
    

    绘制状态的最佳搭档save()和restore():主要用于不停的鼠标移动,用于对当前状态的保存及释放不影响其他操作;可用于重复的绘制图形的变化过程;
    clip():一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内

    4.2 离屏技术

    所谓的离屏技术就是在一个canvas上绘制另外一个canvas,前面使用的绘制图片的API是drawImage(),它分别可以支持,3个、5个和9个参数; 其中第一个参数既可以是图片,也可以是canvas对象!那么我们就可以使用这个方法,在圆上绘制出清晰图了~

    // 圆的半径是mr
    var mr = 100;
    
    // 对应模糊图的左上角起点
    var dx = x - mr,
        dy = y - mr;
    
    // 找出清晰图截图的左上角起点
    var sx = x * scale - mr,
        sy = y * scale- mr;
    
    

        ...
        ctx.clip();
        // 在对应的位置上重新绘制图片
        //drawImage(img,sx,sy,swidth,sheight,x,y,width,height) 9个参数时
        //img: 图片/canvas
        //sx: 图片的X起点
        //sy: 图片的Y起点
        //s要绘制的图片选取的宽度
        //sheight:要绘制的图片选取的高度
        //x,y:图片在canvas上显示的位置
        //width,height:在Canvas上要显示的大小
        ctx1.drawImage(canvas2, sx, sy, 2 * mr, 2 * mr, dx, dy, 2 * mr, 2 * mr);    
        ...
    

    5、鼠标交互事件

    效果:鼠标点击并滑动鼠标产生反应,松开鼠标或者移除画布则失效。

    //定义一个判断鼠标是否是点击滑动的标识符
    var flag;
    
    //鼠标点入事件
    canvas.onmousedown = function(e) {
      flag = true;
      //显示放大镜
    }
    // 鼠标移动事件
    canvas.onmousemove = function(e) {
      if (flag) {
        //显示放大镜
      }
    }
    //鼠标松开事件
    canvas.onmouseup = function(e) {
      flag = false;
      // 隐藏放大镜
    }
    //鼠标离开事件
    canvas.onmouseout = function(e) {
      flag = false;
      // 隐藏放大镜
    }
    

    完整代码:

    var scale = 3;
    var mr = 150;
    var photo = {
      //初始化
      init: function() {
        var that = this;
    
        that.canvas = document.getElementById('canvas');
        that.ctx = that.canvas.getContext('2d');
    
        that.canvas2 = document.getElementById('canvas2');
        that.ctx2 = that.canvas2.getContext('2d');
    
        that.canvas.width = 800;
        that.canvas.height = 500;
    
        that.canvas2.width = that.canvas.width * scale;
        that.canvas2.height = that.canvas.height * scale;
        that.image1 = new Image();
        that.image1.src = "./name3.jpg";
    
        that.image2 = new Image();
        that.image2.src = "./name4.jpg";
    
        that.image1.onload = function() {
          that.ctx.drawImage(that.image1, 0, 0, that.canvas.width, that.canvas.height);
        };
    
        that.image2.onload = function() {
          that.ctx2.drawImage(that.image2, 0, 0, that.canvas2.width, that.canvas2.height);
          that.moveEvt();
        };
      },
    
      bigerImage: function(x, y) {
        var that = this;
        var imageX = x * scale,
          imageY = y * scale,
          sx = imageX - mr,
          sy = imageY - mr;
    
        var dx = x - mr,
          dy = y - mr;
    
        that.ctx.save();
    
        that.ctx.strokeStyle = "#9eddf1";
        that.ctx.lineWidth = 3;
    
        that.ctx.beginPath();
        that.ctx.arc(x, y, mr, 0, Math.PI * 2);
    
    
        that.ctx.shadowColor = "#6ed25b";
        that.ctx.shadowBlur = 10;
    
        that.ctx.stroke();
        that.ctx.clip();
    
        that.ctx.drawImage(that.canvas2, sx, sy, 2 * mr, 2 * mr, dx, dy, 2 * mr, 2 * mr);
    
        that.ctx.restore();
      },
    
      //移动
      moveEvt: function() {
        var that = this;
        that.canvas.onmousedown = function(e) {
        	that.flag = true;
          that.showImage(e);
        }
    
        that.canvas.onmousemove = function(e) {
          if (that.flag) {
            that.showImage(e)
          }
        }
    
        that.canvas.onmouseup = function(e) {
          that.hideImage(e)
        }
    
        that.canvas.onmouseout = function(e) {
          that.hideImage(e)
        }
      },
    
      showImage: function(e) {
        e.preventDefault()
        var x = e.offsetX,
          y = e.offsetY,
          that = this;
        that.ctx.clearRect(0, 0, that.canvas.width, that.canvas.height);
        that.ctx.drawImage(that.image1, 0, 0, that.canvas.width, that.canvas.height);
        that.bigerImage(x, y);
      },
    
      hideImage: function(e) {
        e.preventDefault()
        var that = this;
        
        that.flag = false;
        that.ctx.clearRect(0, 0, that.canvas.width, that.canvas.height);
        that.ctx.drawImage(that.image1, 0, 0, that.canvas.width, that.canvas.height);
      }
    }
    
    window.onload = function() {
      photo.init();
    }
    
    

    转载请说明出处,谢谢!

  • 相关阅读:
    从零开始学习Sencha Touch MVC应用之六
    从零开始学习Sencha Touch MVC应用之七
    从零开始学习Sencha Touch MVC应用之四
    从零开始学习Sencha Touch MVC应用之四
    从零开始学习Sencha Touch MVC应用之七
    从零开始学习Sencha Touch MVC应用之五
    从零开始学习Sencha Touch MVC应用之三
    JpGraph
    thinkphp RBAC 详解
    PHPExcel常用方法总结
  • 原文地址:https://www.cnblogs.com/webhmy/p/14015917.html
Copyright © 2020-2023  润新知