如何用Canvas实现图片局部放大镜功能?

摘要:最近我在可视化课程中学习了如何在Canvas中利用像素处理来实现滤镜效果,在这节课程的结尾留了一道局部放大镜的题目,提示我们用像素处理的方式去实现这个效果,最终实现随着鼠标移动将图片局部放大,以下是我对这个效果的简单实现。
前言 最近我在可视化课程中学习了如何在Canvas中利用像素处理来实现滤镜效果,在这节课程的结尾留了一道局部放大镜的题目,提示我们用像素处理的方式去实现这个效果,最终实现随着鼠标移动将图片局部放大,本着把学到的内容落地实践的想法,我就去思考了一番,但很不幸,我思考了好几天也没思考出结果,因为刚开始我想的一直是在一个Canvas上来操作,但是一来我对Canvas API还并不是很熟悉,二来我对像素处理还不够熟练,然后第三是如果原图的部分像素被处理了,那下一次放大就会有问题,因此我最终放弃了这个思路,选择了再增加一个Canvas来完成最终的效果,以下就是利用这种方式实现图片局部放大的效果。 像素处理 在实现这个效果之前,我们先来了解一下如何处理像素,有些小伙伴可能不太清楚,所以这里简单说一下,在屏幕上我们知道所有显示的内容都是由像素点组成的,那么在处理像素之前,我们需要先获取到像素信息,那么Canvas就是提供了一个API叫做getImageData让我们可以获取到画布上的像素信息,最终这个API返回的是一个ImageData类型的值,关于这个API的具体描述可以参考对应的MDN页面。 ImageData类型的数据包含三个属性,包括data、width、height。width和height简单来说,就是被提取像素信息的区域的宽高,最主要的像素信息是在这个data属性中。data属性指向一个数组类型的值,准确来说是Uint8ClampedArray的实例,Uint8ClampedArray表示8 位无符号整型固定数组,也就是说其中的元素是0到255之间的整数,我们知道一个像素的颜色信息可以使用rgba四个分量表示,那么我们就得出在data数组中每四个元素就能表示一个像素点的信息,因此data数组的长度就是width * height * 4,通过操作这个数组的元素就能对像素进行处理。 了解完像素处理,我们就可以开始进行具体的实现了。 具体实现 <canvas ref="canvasRef" width="0" height="0"></canvas> <canvas ref="magnifier" width="0" height="0"></canvas><!-- 放大镜 --> 1. 准备工作 在实现放大效果之前,我们需要先把图片加载到Canvas上: (async function() { const img = await loadImage('src/assets/girl1.jpg'); canvasRef.value.width = img.width; canvasRef.value.height = img.height; context.drawImage(img, 0, 0); }()); 这里loadImage方法是通过Image对象来异步加载图片,然后通过drawImage方法将图片绘制到画布上。 接着设置一个要放大的区域,也就是以鼠标坐标为中心,多少半径以内的内容要被放大,这里我设置一个变量originSize用于存储原图大小,并设置一个5倍的放大倍数。 let originSize = 40; // 原图大小 let zoom = 5; // 放大倍数 (async function() { // ... magnifier.value.width = originSize * zoom; magnifier.value.height = originSize * zoom; }()); 用作于放大镜的magnifier,我们使用originSize * zoom来设置它的宽高。 2. 鼠标移动事件监听 接下来就是主要的代码实现。 首先是添加鼠标移动事件的监听: const addEvent = () => { canvasRef.value.addEventListener('mousemove', mouseDownHandler); }; addEvent(); 然后我们就来实现mouseDownHandler函数。
阅读全文