Canvas无法直接用CSS filter调局部亮度,需用getImageData/putImageData像素操作或SVG遮罩;推荐前者,通过缩放RGB值(k≠1)调整亮度,避免溢出。

HTML5 Canvas 中无法直接用 CSS filter 调局部亮度
HTML5 本身没有“局部亮度滤镜”这个内置功能。CSS 的 filter: brightness() 只能作用于整个元素,不能指定区域。真要调局部亮度,必须借助 Canvas 的像素级操作,或用 SVG 配合遮罩——但后者兼容性和控制精度远不如 Canvas。
用 Canvas getImageData + putImageData 调局部亮度
这是最可控、浏览器支持最广(IE9+)的方案。核心是:读取目标区域像素 → 按公式调整 RGB 值 → 写回画布。注意亮度不是简单加减,而是按比例缩放(避免溢出):
- 亮度系数
k> 1 表示提亮,kk = 1 为原始 - R、G、B 分别乘以
k,再用Math.min(255, Math.max(0, ...))截断 - Alpha 通道保持不变,否则会破坏透明度
- 操作前用
ctx.save()/ctx.restore()避免影响其他绘制
const imageData = ctx.getImageData(x, y, width, height);
const data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
data[i] = Math.min(255, Math.max(0, data[i] * k)); // R
data[i+1] = Math.min(255, Math.max(0, data[i+1] * k)); // G
data[i+2] = Math.min(255, Math.max(0, data[i+2] * k)); // B
// data[i+3] 不动(alpha)
}
ctx.putImageData(imageData, x, y);用 CSS mask-image + filter 实现“伪局部亮度”
如果只是视觉上“看起来”只亮某一块,且不需要精确像素控制,可用 CSS 遮罩配合 filter。但要注意:这本质是把整个图层变亮,再用 mask “扣出”局部可见区,实际是“局部可见的全局亮度变化”,不是真正局部处理。
- mask-image 需是灰度图:白色=完全显示,黑色=隐藏,灰色=半透
- 必须设置
mask-type: luminance(默认是 alpha,容易出错) - Firefox 对
mask-image支持较弱,建议加-webkit-mask-image兼容 - 亮度值写在父容器上,mask 写在子容器上,层级关系不能反
WebGL 方案(Three.js 或原生)适合高频/大图场景
Canvas 像素遍历在高分辨率图或频繁更新时明显卡顿(尤其移动端)。这时该切 WebGL:把图像传为纹理,用 fragment shader 对 UV 坐标做条件判断,只对指定区域应用亮度系数。例如:
立即学习“前端免费学习笔记(深入)”;
if (uv.x > 0.3 && uv.x < 0.7 && uv.y > 0.2 && uv.y < 0.6) {
color.rgb *= 1.3; // 中央区域提亮
}Three.js 可封装成 ShaderMaterial,但学习成本和调试难度明显上升。小项目不推荐,动态人像/视频滤镜类需求才值得投入。
真正难的不是写哪段代码,而是决定“局部”怎么定义:是固定坐标矩形?还是基于人脸检测的动态 ROI?后者必须接 face-api.js 或 WebRTC,整个链路就从 CSS 问题升级成工程问题了。










