canvas 滤镜和反色需通过 getimagedata 读取并修改 rgba 像素数组,再用 putimagedata 写回;须确保图像加载完成、尺寸匹配、同源;灰度采用加权公式(0.299r+0.587g+0.114b),反色为 255-r/g/b;alpha 保持不变,修改后必须显式写回画布。

Canvas 实现滤镜和反色,核心是直接读写像素数据,不是靠 CSS 或绘图命令,而是通过 getImageData 拿到原始 RGBA 数组,修改后再用 putImageData 写回画布。
确保图像已加载且尺寸匹配
这是所有像素操作的前提,否则会报错或显示异常:
- 必须等
img.onload触发后再绘制图像到 canvas,避免读取空白区域 - canvas 的
width和height应设为与图片完全一致,否则getImageData取出的区域可能错位或截断 - 图像需同源(本地文件或同域资源),跨域图片会触发安全限制,无法读取像素
灰度滤镜:按人眼感知加权计算
简单平均((R+G+B)/3)会让图像发灰、层次模糊;标准做法是加权还原亮度感知:
- 遍历
data数组,步长为 4(跳过 R、G、B、A 四个分量) - 提取
data[i](R)、data[i+1](G)、data[i+2](B) - 计算:
gray = data[i] * 0.299 + data[i+1] * 0.587 + data[i+2] * 0.114 - 取整后同时赋给三个通道:
data[i] = data[i+1] = data[i+2] = gray | 0 - Alpha(
data[i+3])保持原值,不参与运算
反色滤镜:RGB 各通道逐值取反
原理就是颜色关于 127.5 对称,实现极简且安全:
- 对每个像素的 R、G、B 分别执行:
data[i] = 255 - data[i]、data[i+1] = 255 - data[i+1]、data[i+2] = 255 - data[i+2] - Uint8ClampedArray 自动约束结果在 0–255 范围,无需额外判断越界
- Alpha 值跳过,保留原始透明度
写回画布并注意性能边界
修改完 data 后必须显式写回,否则画布不会变化:
- 调用
ctx.putImageData(imageData, 0, 0)将处理后的数据渲染到画布左上角 - 该操作同步执行、开销较大,避免在
requestAnimationFrame循环中高频调用 - 如需实时处理大图,可考虑离屏 Canvas 预计算,或用 Web Worker 拆分像素任务
- 调试时可用
console.log(data.subarray(0, 16))查看前 4 个像素的 RGBA 值,验证逻辑是否生效
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











