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


Posted in HTML / CSS onNovember 26, 2020

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

一张模糊的图片:

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

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

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

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

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();

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

绘制状态的最佳搭档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;

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

...
    ctx.clip();
    // 在对应的位置上重新绘制图片
    //drawImage(img,sx,sy,swidth,sheight,x,y,width,height) 9个参数时
    //img: 图片/canvas
    //sx: 图片的X起点
    //sy: 图片的Y起点
    //swidth:要绘制的图片选取的宽度
    //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();
}

到此这篇关于Canvas实现放大镜效果完整案例分析(附代码)的文章就介绍到这了,更多相关Canvas 放大镜内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章,希望大家以后多多支持三水点靠木!

HTML / CSS 相关文章推荐
CSS3制作气泡对话框的实例教程
May 10 HTML / CSS
谈谈对css属性box-sizing的了解
Jan 04 HTML / CSS
CSS3 实现的加载动画
Dec 07 HTML / CSS
程序设计HTML5 Canvas API
Apr 08 HTML / CSS
HTML5使用DOM进行自定义控制示例代码
Jun 08 HTML / CSS
谷歌浏览器小字体处理方案即12px以下字体
Dec 17 HTML / CSS
HTML5的一个显示电池状态的API简介
Jun 18 HTML / CSS
详解HTML5 data-* 自定义属性
Jan 24 HTML / CSS
详解HTML5将footer置于页面最底部的方法(CSS+JS)
Oct 11 HTML / CSS
HTML5 Canvas 实现K线图的示例代码
Dec 23 HTML / CSS
简洁自适应404页面HTML好看的404源码
Dec 16 HTML / CSS
CSS实现两列布局的N种方法
Aug 02 HTML / CSS
HTML5在手机端实现视频全屏展示方法
Nov 23 #HTML / CSS
关于HTML5+ API plusready的兼容问题
Nov 20 #HTML / CSS
Html5原生拖拽相关事件简介以及基础实现
Nov 19 #HTML / CSS
Canvas获取视频第一帧缩略图的实现
Nov 11 #HTML / CSS
使用layui框架实现点击左侧导航切换右侧内容且右侧选项卡跟随变化的效果
Nov 10 #HTML / CSS
使用layui实现左侧菜单栏及动态操作tab项的方法
Nov 10 #HTML / CSS
萌新HTML5 入门指南(二)
Nov 09 #HTML / CSS
You might like
PHP如何通过传引用的思想实现无限分类(代码简单)
2015/10/13 PHP
使用PHP uniqid函数生成唯一ID
2015/11/18 PHP
php魔法函数与魔法常量使用介绍
2017/07/23 PHP
Laravel中日期时间处理包Carbon的简单使用
2017/09/21 PHP
js中将多个语句写成一个语句的两种方法小结
2007/12/08 Javascript
COM中获取JavaScript数组大小的代码
2009/11/22 Javascript
网页防止tab键的使用快速解决方法
2013/11/07 Javascript
浅谈JavaScript正则表达式分组匹配
2015/04/10 Javascript
详解原生JavaScript实现jQuery中AJAX处理的方法
2016/05/10 Javascript
Angular2-primeNG文件上传模块FileUpload使用详解
2017/01/14 Javascript
js基础之事件捕获与冒泡原理
2019/10/09 Javascript
p5.js实现故宫橘猫赏秋图动画
2019/10/23 Javascript
JS控制只能输入数字并且最多允许小数点两位
2019/11/24 Javascript
vue使用map代替Aarry数组循环遍历的方法
2020/04/30 Javascript
Vue使用screenfull实现全屏效果
2020/09/17 Javascript
Python获取linux主机ip的简单实现方法
2016/04/18 Python
Python实现树的先序、中序、后序排序算法示例
2017/06/23 Python
Python实现的文本对比报告生成工具示例
2018/05/22 Python
使用Python抓取豆瓣影评数据的方法
2018/10/17 Python
Python3.5内置模块之time与datetime模块用法实例分析
2019/04/27 Python
python图形用户接口实例详解
2019/12/16 Python
在Python中用GDAL实现矢量对栅格的切割实例
2020/03/11 Python
彻底解决pip下载pytorch慢的问题方法
2021/03/01 Python
HTML5 Canvas实现放大镜效果示例
2020/03/25 HTML / CSS
阿迪达斯奥地利官方商城:adidas.at
2016/10/16 全球购物
美国购买和销售礼品卡平台:Raise
2017/01/13 全球购物
摩托车和ATV零件、配件和服装的首选在线零售商:MotoSport
2017/12/22 全球购物
Lacoste澳大利亚官网:服装、鞋类及配饰
2018/11/14 全球购物
雅诗兰黛澳大利亚官网:Estée Lauder澳大利亚
2019/05/31 全球购物
党员承诺书怎么写
2014/05/20 职场文书
副乡长群众路线教育实践活动个人对照检查材料
2014/09/19 职场文书
县政协领导班子群众路线教育实践活动四风问题整改方案
2014/10/26 职场文书
介绍信应该怎么开?
2019/04/03 职场文书
2019个人工作自我评价范文(3篇)
2019/09/19 职场文书
致男子1500米运动员的广播稿
2019/11/08 职场文书
使用python向MongoDB插入时间字段的操作
2021/05/18 Python