先看效果


上图是一段打码过后的代码截图。

简单说一下实现思路

就是通过创建多个canvas,一个用来绘制原图,一个用来绘制全马赛克图,一个用来绘制笔迹或者叫打码的区域,最后一个canvas用来将三个canvas绘制到一个canvas之上。

主要是通过设置canvas的globalCompositeOperation属性设置“图层”的叠加情况。马赛克图层通过笔迹图层遮罩显示,一开始笔迹图层为空,所以马赛克图层不会显示,通过用户在马赛克图层上涂抹笔迹,马赛克图层显示,从而达到涂抹打马赛克的效果。

废话少说直接上代码

<!DOCTYPE html>
<html><head>
</head><body><div style="position: relative;"><!-- http://cover.acfunwiki.org/cover.php --><!-- <img alt="asd" src="./tmp.png" style="position: absolute;" /> --><canvas id="canvas" style="position: absolute;"></canvas></div><script>let image = new Image()image.src = "./tmp.png"// let canvas:HTMLCanvasElement = document.getElementById("canvas")let canvas = document.getElementById("canvas")let ctx = canvas.getContext("2d")let canvas_1 = document.createElement("canvas")let canvas_layer_1 = canvas_1.getContext("2d") // 用来画原图的图层let canvas_2 = document.createElement("canvas")let canvas_layer_2 = canvas_2.getContext("2d") // 用来画马赛克图的图层let canvas_3 = document.createElement("canvas")let canvas_layer_3 = canvas_3.getContext("2d") // 用来画笔迹的图层image.onload = async () => {canvas_3.width = canvas_2.width = canvas_1.width = canvas.width = image.width;canvas_3.height = canvas_2.height = canvas_1.height = canvas.height = image.height;canvas_layer_1.drawImage(image, 0, 0); // 把图片绘制到画布上// 获取原来图片的像素数据let oldImageData = canvas_layer_1.getImageData(0, 0, image.width, image.height);// 创建一个新的像素数据let newImageData = canvas_layer_2.createImageData(image.width, image.height);// 自己定义一个块的容量,把N个像素作为一个单位// 把图片分块 每一块的size设置为5(自己随便定义的)let size = 10;for (let i = 0; i < oldImageData.width / size; i++) {for (let j = 0; j < oldImageData.height / size; j++) {// 从每一块中随机取出五个像素点的颜色let locations = new Array(5).fill(null).map(x=>{return [i * size + Math.floor(Math.random() * size), j * size + Math.floor(Math.random() * size)]})let color = getPxColor(oldImageData, locations);// 把这个像素点的颜色给这一小块全部铺满for (let m = 0; m < size; m++) {for (let n = 0; n < size; n++) {setPxColor(newImageData, i * size + m, j * size + n, color);}}}}canvas_layer_2.putImageData(newImageData, 0, 0)canvas_layer_3.lineCap="round"canvas_layer_3.lineJoin="round"canvas_layer_3.lineWidth=40canvas_layer_3.fillStyle="blue"canvas.addEventListener("mousedown", mouseHandle)function mouseHandle(e) {if(e.type === "mousedown"){canvas_layer_3.moveTo(e.offsetX, e.offsetY);canvas.addEventListener("mousemove", mouseHandle)canvas.addEventListener("mouseup", mouseHandle)}else if(e.type === "mousemove"){canvas_layer_3.lineTo(e.offsetX, e.offsetY);}else if(e.type === "mouseup"){canvas.removeEventListener("mousemove", mouseHandle)canvas.removeEventListener("mouseup", mouseHandle)}canvas_layer_3.stroke()}function draw() {ctx.clearRect(0,0,canvas.width,canvas.height)ctx.drawImage(canvas_3,0,0)ctx.globalCompositeOperation="source-in";ctx.drawImage(canvas_2,0,0)ctx.globalCompositeOperation="destination-over";ctx.drawImage(canvas_1,0,0)requestAnimationFrame(draw)}requestAnimationFrame(draw)}// 设置指定坐标位置像素的值function setPxColor(imageData, x, y, color) {imageData.data[(y * imageData.width + x) * 4] = color[0];imageData.data[(y * imageData.width + x) * 4 + 1] = color[1];imageData.data[(y * imageData.width + x) * 4 + 2] = color[2];imageData.data[(y * imageData.width + x) * 4 + 3] = color[3];}function getPxColor(imageData, locations) {let color = [];// 有多宽,就是一排有多少个像素点let width = imageData.width;// 颜色混合之后再返回color = locations.reduce((preVal, currVal, index)=>{let x = locations[index][0]let y = locations[index][1]if(index === 0){preVal[0] = imageData.data[(y * width + x) * 4];preVal[1] = imageData.data[(y * width + x) * 4 + 1];preVal[2] = imageData.data[(y * width + x) * 4 + 2];preVal[3] = imageData.data[(y * width + x) * 4 + 3];} else {preVal[0] = Math.round(preVal[0] + (imageData.data[(y * width + x) * 4] - preVal[0]) * 0.5);preVal[1] = Math.round(preVal[0] + (imageData.data[(y * width + x) * 4 + 1] - preVal[0]) * 0.5);preVal[2] = Math.round(preVal[0] + (imageData.data[(y * width + x) * 4 + 2] - preVal[0]) * 0.5);preVal[3] = preVal[3];}return preVal},[])return color;}</script>
</body></html>

Canvas 原生实现图片涂抹打马赛克功能相关推荐

  1. android图片美化开源,GitHub - xingxing-yan/BLImage: Android中美化图片的库。功能包括滤镜,贴纸,标签,裁剪,涂鸦,亮度,饱和度,对比度,马赛克等功能...

    BLImage Android中美化图片的库.功能包括滤镜,贴纸,标签,裁剪,涂鸦,亮度,饱和度,对比度,马赛克等功能 效果图 添加依赖: 在project的build.gradle中添加: allp ...

  2. 使用canvas实现对图片的批量打码

    最近有个需求,利用h5的canvas对图片一些涉及个人隐私的地方进行打码再上传,而且最好能实现批量打码.意思是在一张图片上对哪些地方做了打码,后续的所有图片都在同样的地方也可以自动打上码,不用人工一张 ...

  3. 前端线上图片怎么生成马赛克?

    前言 说起图片的马赛克,可能一般都是由后端实现然后传递图片到前端,但是前端也是可以通过canvas来为图片加上马赛克的,下面就通过码上掘金来进行一个简单的实现. 实现 实现过程 <img src ...

  4. 【Android 内存优化】Android 原生 API 图片压缩原理 ( 哈夫曼编码开关 | 哈夫曼编码原理 | libjpeg-turbo 函数库 )

    文章目录 一. 哈夫曼编码开关 二. 哈夫曼编码原理 三. libjpeg-turbo 函数库 四. libjpeg-turbo 函数库下载 [Android 内存优化]图片文件压缩 ( Androi ...

  5. 【Android 内存优化】Android 原生 API 图片压缩原理 ( Bitmap_compress 方法解析 | Skia 二维图形库 | libjpeg 函数库 | libpng 函数库 )

    文章目录 一. 图片质量压缩方法 二. Skia 二维图形库 三. libjpeg.libpng 函数库引入 在博客 [Android 内存优化]图片文件压缩 ( Android 原生 API 提供的 ...

  6. 【Android 内存优化】Android 原生 API 图片压缩原理 ( 图片质量压缩方法 | 查找 Java 源码中的 native 方法对应的 C++ 源码 )

    文章目录 一. 图片质量压缩方法 二. 查找对应的 Native 方法源码 三. 分析 Bitmap.cpp 中动态注册 Native 方法 在博客 [Android 内存优化]图片文件压缩 ( An ...

  7. load方法引入本地html报错,分享基于plus.downloader的图片懒加载功能,支持本地缓存v1.1.0...

    今天试用了下hello mui上的图片懒加载功能,发现有些地方还无法满足我的需求,ajax动态加载的时候无法实现懒加载. 然后又看了下36kr的示例,因为代码关系实在太多了,耦合度比较高,遂自己动手写 ...

  8. java canvas 缩放图片_详解如何用HTML5 Canvas API控制图片的缩放变换

    摘要:这篇HTML5栏目下的"详解如何用HTML5 Canvas API控制图片的缩放变换",介绍的技术点是"html5_canvas.canvas.Html5.控制图片 ...

  9. app canvas渲染后图片黑色_H5 基于 canvas 实现电子签名并生成PDF文档

    (给前端大全加星标,提升前端技能) 转自:coyota666 https://juejin.cn/post/6901273585428463624 前言 电子签名通俗来说就是通过技术手段实现在电子文档 ...

  10. js html转盘点名,原生JS实现简易随机点名功能

    定时器的工作原理,这里将用引用How JavaScript Timers Work中的例子来解释定时器的工作原理,该图为一个简单版的原理图.· 上图中,左侧数字代表时间,单位毫秒:左侧文字代表某一个操 ...

最新文章

  1. 树言树语:谁动了苹果的弦
  2. python websocket server 解决中文乱码
  3. python中文什么意思-python是什么
  4. android.graphic.Path
  5. 速来围观MOS管的选择步骤
  6. 成功解决TabError: inconsistent use of tabs and spaces in indentation
  7. CSS 锦囊[收藏]
  8. java加密文件夹_使用java.util.zip压缩文件夹,支持加密,增加描述
  9. Redis4.0 Cluster — Centos7
  10. 前端学习(1606):数据请求与json-server
  11. Android代码优化
  12. dbf转成excel_DBF Converter将DBF文件转换成Excel表格教程
  13. ArcGIS矢量化并进行拓扑检查(附练习数据下载)
  14. 个人网盘源码 本地网盘网站源码
  15. Flask-SQLAlchemy牛刀小试
  16. 艺术签名微信小程序源码/支持微信流量主
  17. xp2 server application error 错误解决
  18. WARNING: Ignoring invalid distribution -ip 解决方案
  19. python byte类型_Python3的字节类型(bytes)
  20. ⭐算法入门⭐《堆》中等01 —— LeetCode 面试题 17.09. 第 k 个数

热门文章

  1. bmp格式如何转换成png格式
  2. IAR调试stm8的优化设置
  3. 解决sudo: no valid sudoers sources found, quitting
  4. 蔡氏电路matlab仿真实代码验,基于蔡氏电路的MATLAB仿真
  5. 使用canvas将多张图片合并为一张
  6. 北风:个人如何在职场中野蛮生长
  7. python语法报错_1、Python语法及报错总结 - 随笔分类 - 走路带风的帅界扛把子 - 博客园...
  8. JavaWeb - 小米商城网 - 项目启动
  9. 2019重庆大学计算机学院研究生,【计算机】计算机学院举行2019级研究生年级大会...
  10. 修真院教学模式四大体系之职业素养