原生JavaScript + Canvas实现图片局部放大器
类似操作像素的博主还写过一篇文章:使用canvas给图片增加滤镜
文章目录
1. 效果图
有两种放大模式,分别为拖拽放大以及单纯的hover放大,已下是效果图:
2. 原理
两种局部放大效果主要使用的均为canvas的getImageData以及putImageData。
(以上两个api详细介绍可以点击蓝色链接,跳转到MDN查看)
操纵
getImageData函数返回的ImageData来进行放大效果, 以下是详细实现方法:
2.1. 拖拽放大
当鼠标在canvas中触发mousedown事件时,通过
getImageData函数获取当前画布的
ImageData信息,并且复制一份当前画布信息,对其每个像素点的alpha设置为原来的一半,形成半透明效果 (
imageData为连续的
Uint8ClampedArray(8位无符号整形固定数组), 每4个项表示一个像素点,r红,g绿,b蓝,a透明度)。
当鼠标触发mousemove事件时,通过
putImageData函数将上一步复制的半透明画布信息,动态放到canvas中。
最后当鼠标触发moveup时,将该部分像素信息铺满整个画布即可。
这里有个问题需要注意,
putImageData函数同时使用了设备像素以及css像素两种计量单位,当指定了canvas偏移量时需要以CSS像素为单位,然而在指定图像数据中的位置时则需要以设备像素为单位。
/** * 生成矩形框内部半透明图像 */ function restoreRubberbandPixels() { // imageData中的width和height指的是canvas所含设备像素数量,例如有一个200*200像素的canvas // 那么就总共含有4w个css像素点,若是浏览器在横竖两个方向都有两个设备像素来表示每个css像素的话就有 // 16w个(400*400)个像素点 // 获取像素比 const deviceWidth = imageData.width / canvas.width; const deviceHeight = imageData.height / canvas.height; context.putImageData(imageData, 0, 0); context.putImageData(imageDataCopy, 0, 0, rubberbandRectangle.left + context.lineWidth, rubberbandRectangle.top + context.lineWidth, (rubberbandRectangle.width - 2 * context.lineWidth) * deviceWidth, (rubberbandRectangle.height - 2 * context.lineWidth) * deviceHeight ); }
2.2. hover放大
该部分实现原理较上一小节来说比较简单,只需监听鼠标mousemove事件,首先获取当前鼠标位置自定义大小矩形框的
ImageData信息用于下一次鼠标移动恢复原始图像使用,然后就可以通过
drawImage函数的9个参数来进行放大图像
function drawMagnifyGlass(mouse) { let scaledMagnifyRectangle = null; magnifyRectangle.x = mouse.x; magnifyRectangle.y = mouse.y; imageData = context.getImageData( magnifyRectangle.x - magnifyGlassRadius, magnifyRectangle.y - magnifyGlassRadius, magnifyRectangle.width, magnifyRectangle.height, ) context.save(); scaledMagnifyRectangle = { width: magnifyRectangle.width * magnifycationScale, height: magnifyRectangle.height * magnifycationScale, } // 画圆形形状 setClip(); // 放大图像 context.drawImage(canvas, magnifyRectangle.x - magnifyGlassRadius, magnifyRectangle.y - magnifyGlassRadius, magnifyRectangle.width, magnifyRectangle.height, magnifyRectangle.x - 2 * magnifyGlassRadius, magnifyRectangle.y - 2 * magnifyGlassRadius, scaledMagnifyRectangle.width, scaledMagnifyRectangle.height ) context.restore(); }
3. 代码
代码地址: https://github.com/TheKiteRunners/-JavaScript-Canvas-/tree/master
注意该代码要放到服务器中运行,否则会触发canvas的安全问题:
基于安全考量,canvas规范允许绘制不属于自己的(也就是其他域中的)图像,然而你不能通过canvas API保存或修改其他域中的图像
canvas安全机制如下:
每个canvas都有一个名为origin-clean的标志位,它的初始值为true,如果使用drawImage绘制了一幅其他域中的图像,那么origin-clean的值就会被设置为false。与此类似,如果用drawImage将一个origin-clean标志位false的canvas绘制到当前的canvas中,那么它的origin-clean标志也会被设置为false。
就其本身而言,将canvas的origin-clean设置为false,并不会立刻导致诸如抛出异常这样的反应来,不过如果在origin-clean标志位false的canvas上调用toDataURL或getImageData方法,那么此时浏览器就会抛出SECURITY_ERR异常
因此最简单的方法可以npm一个全局的http-server静态服务器即可运行该代码。
1. npm install http-server -g 2. 项目路径下打开控制台输入:http-server -p 8081 3. 打开浏览器输入地址即可
参考链接: David Geary著 HTML5 Canvas核心技术 189-223页
- 点赞
- 收藏
- 分享
- 文章举报
- 原生javascript实现图片弹窗交互效果
- Javascript与HTML5的canvas实现图片旋转效果
- 原生javascript实现图片按钮切换
- 原生javascript实现图片按钮切换
- 原生javascript FileReader对象实现图片上传本地预览效果
- 用Canvas+Javascript FileAPI 实现一个跨平台的图片剪切、滤镜处理、上传下载工具
- 原生JavaScript实现图片切换
- 原生javascript实现图片滚动、延时加载功能
- JavaScript+Canvas实现彩色图片转换成黑白图片的方法分析
- javascript - 原生 js 实现图片“自动+无缝”滚屏效果
- 原生javascript实现图片轮播效果
- 原生javascript实现图片轮播效果——续
- [H5-Compress-Image]利用canvas实现 javascript 图片压缩处理_基于requirejs模块化的代码实现
- javascript结合canvas实现图片旋转效果
- 【JavaScript】基于H5 canvas实现的画板绘图工具(类似你画我猜)——整合颜色选取、保存图片到本地功能
- JavaScript+html5 canvas实现图片破碎重组动画特效
- 使用原生JavaScript的Canvas实现拖拽式图形绘制,支持画笔、线条、箭头、三角形、矩形、平行四边形、梯形以及多边形和圆形,不依赖任何库和插件,有演示demo
- 原生 JavaScript 实现图片切换
- 原生javascript实现图片弹窗交互效果
- 原生javaScript实现图片延时加载的方法