canvas滤镜进阶关键在于直接操作imagedata.data:马赛克通过区块采样与填充实现降分辨率效果,模糊则基于高斯核邻域加权平均;需注意跨域限制、性能优化及边界处理。

Canvas滤镜进阶的关键在于直接操作像素数据,马赛克和模糊看似效果不同,底层都依赖对 imageData.data 的读取与重写。只要掌握 getImageData 和 putImageData 的配合逻辑,再理解区块采样与邻域加权两种思路,就能稳定实现这两种效果。
马赛克:按块采样+填充
马赛克本质是“降分辨率再放大”——把图像划分成若干矩形区块,每个区块内只保留左上角(或平均)颜色,再用该颜色填满整个区块。
- 先用 ctx.getImageData(0, 0, width, height) 获取全部像素数据
- 设定马赛克单元尺寸(如 blockSize = 10),遍历每个区块起点:x 从 0 到 width 步长 blockSize,y 同理
- 在每个区块内,取左上角像素的 r/g/b 值(data[(y * width + x) * 4] 等),或计算该区域内所有像素的平均色
- 用 ctx.fillStyle = `rgb(${r},${g},${b})` + fillRect(x, y, blockSize, blockSize) 填充该区块
模糊:邻域加权平均(高斯核)
模糊不是简单取周围像素平均,而是用高斯函数给不同距离的像素分配权重,中心最强、边缘渐弱,这样边缘更自然、无明显方块感。
- 预生成一维高斯核数组(如半径 3,σ ≈ 1),归一化使其和为 1
- 先沿 x 方向逐行卷积:对每个像素,取左右 radius 个像素,加权求和得到新 r/g/b
- 再沿 y 方向逐列卷积:对上一步结果,取上下 radius 个像素,同样加权求和
- 注意边界处理:超出画布范围的坐标要跳过,或做镜像/复制等填充
绕不开的跨域问题
调用 getImageData 时若图片来自外站,浏览器会抛出 tainted canvas 错误。这不是代码问题,而是安全限制。
- 本地开发时,不能直接用 file:// 协议打开 HTML——必须起一个本地服务(如 http-server、Live Server 插件)
- 线上部署时,确保图片服务器设置了 CORS 头(Access-Control-Allow-Origin: * 或指定域名)
- 若无法改服务端,可将图片转为 base64 字符串内联,或用代理接口中转
性能与体验优化点
像素级运算容易卡顿,尤其在大图或低配设备上,需主动控制开销。
- 对高清图做预缩放:用 drawImage 先绘制到小尺寸离屏 canvas,处理完再放大回显
- 马赛克可跳过逐像素循环,直接用 fillRect;模糊则建议用 Web Worker 搬运计算,避免阻塞主线程
- 用户调整参数(如模糊半径、马赛克格子大小)时,不要实时重算,改为“应用”按钮触发,减少无效渲染











