html5 canvas图像马赛克打码需同源图片、本地服务运行、图片加载完成后再操作、canvas尺寸匹配;主流方法有fillrect填色法(取色+填充,易调试)和drawimage缩放法(禁用平滑后拉伸,性能优)。

HTML5 Canvas 实现图像马赛克打码,核心是手动控制像素块的采样与重绘,不是靠 CSS 滤镜或一键 API。关键在于把图像划分成规则网格,对每个网格统一填色——要么取左上角像素,要么算平均色,再用 fillRect 或缩放 drawImage 填满整个块。
必须满足的前提条件
不处理这些,代码会静默失败或报错:
- 图片必须同源(或服务端配置 CORS),否则
getImageData触发SecurityError - 不能双击 HTML 文件直接打开(
file://协议被浏览器视为跨域),需起本地服务,例如:python3 -m http.server 8000 - 务必等图片加载完成再操作:
img.onload = () => { drawAndMosaic() },否则读到的是空数据 - Canvas 尺寸要和图片自然尺寸一致(或按比例缩放后手动校准),避免拉伸失真
两种主流实现方式对比
选哪种取决于性能要求和效果偏好:
-
fillRect 填色法(推荐初学者):遍历每个马赛克单元(如 12×12),用
getImageData读取该区域像素 → 取左上角或平均 RGB →ctx.fillStyle设色 →fillRect填满整块。逻辑直白,易调试,适合局部打码 -
drawImage 缩放法(更高效):先设
ctx.imageSmoothingEnabled = false,然后对每个小区域反复调用drawImage,把 8×8 区域“拉伸”画到 32×32 位置。浏览器用最近邻插值,天然生成硬边马赛克,省去颜色计算,性能更好
只对指定区域打码(比如人脸)
全图处理太慢,实际应用中几乎都只处理 ROI(Region of Interest):
- 定义目标矩形:
{x: 100, y: 200, width: 80, height: 80} - 循环范围限定在该区域内:
for (let y = roi.y; y - 读取像素时也只读子区域:
ctx.getImageData(roi.x, roi.y, roi.width, roi.height),避免整图读取开销 - 注意坐标映射:若 Canvas 有 CSS 缩放或滚动,用
getBoundingClientRect()校准鼠标/触摸点到 canvas 像素坐标
动态打码(随鼠标实时更新)优化技巧
避免每动一下就重绘全图,否则卡顿明显:
- 记录上一帧打码区域
lastRect和当前区域newRect,取并集作为重绘范围 - 只对这个合并区域执行采样→填色→写回流程
- 用
requestAnimationFrame节流,保证稳定 60fps - 移动端需转换 touch 坐标:
const x = (e.touches[0].clientX - rect.left) * (canvas.width / rect.width)
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











