Canvas反色应优先用getImageData手动像素运算,因ctx.filter跨浏览器支持差;大图或实时场景可选WebGL或OffscreenCanvas;SVG反色仅适用于SVG元素本身。
ctx.filter 做反色不靠谱直接设 ctx.filter = "invert(100%)" 看似简单,但实际在多数浏览器(尤其是 Safari 和旧版 Chrome)中不生效,或仅对 drawImage() 生效、对 fillRect() / text 等无效。这不是写法错,是规范支持不一致 —— ctx.filter 本质是 CSS filter 的 canvas 映射,而 Canvas 2D 上下文对它的实现非常有限。
getImageData() + 手动像素运算才是可靠反色这是跨浏览器稳定、可控、可调试的方案。核心是读取像素数组,对每个 r、g、b 分量做 255 - value 运算,a(alpha)保持不变。
实操注意点:
getImageData() 抛 SecurityError)ctx.clearRect(0, 0, width, height) 避免残留putImageData() 写回,不是重绘
简例:
立即学习“前端免费学习笔记(深入)”;
const img = new Image();
img.onload = () => {
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
canvas.width = img.width;
canvas.height = img.
height;
ctx.drawImage(img, 0, 0);
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
data[i] = 255 - data[i]; // r
data[i+1] = 255 - data[i+1]; // g
data[i+2] = 255 - data[i+2]; // b
// data[i+3] alpha 不变
}
ctx.putImageData(imageData, 0, 0);
};
img.src = 'photo.jpg';
当图像大(如 >2000×2000)、需实时处理(视频帧)或频繁切换滤镜时,纯 CPU 的 getImageData 会卡顿。这时:
vec4(1.0 - textureColor.rgb, textureColor.a)
OffscreenCanvas 在 Worker 中做像素计算,避免阻塞主线程 只适用于静态 SVG 内容如果目标是 SVG 元素(比如一个 或 ),可用 SVG 滤镜:
但这个方案和 HTML5 Canvas 无关,也不能用于 Canvas 绘制内容,更不能动态控制强度(比如 invert(70%))。值矩阵里四个 1 是偏移项,对应 RGB 各加 1 → 实际是 1 - r 等效,所以是真正反色。
真正容易被忽略的是:Canvas 反色不是“开个开关”,而是明确区分「目标载体」——你反的是 Canvas 上的位图?SVG 图元?还是 CSS 渲染层?选错路径,后面全是兼容性补丁。