Canvas 2D 的 ctx.filter 不支持浮雕滤镜,需用 SVG 的 feConvolveMatrix 或手动 getImageData 像素计算实现;SVG 方案需正确配置 kernelMatrix、edgeMode 和 bias,Canvas 方案需灰度化、Sobel 差分及溢出保护。

HTML5 Canvas 的 ctx.filter 不支持浮雕滤镜
直接用 ctx.filter = "url(#emboss)" 或类似 CSS filter 值是无效的——Canvas 2D 上下文的 filter 属性只接受 CSS filter 函数(如 blur(2px)、contrast(1.2)),但不支持自定义 SVG 滤镜或 url() 引用,更没有内置浮雕(emboss)效果。
用 SVG 实现浮雕质感
真正能做浮雕的是 SVG 的 ,它通过卷积核对图像像素加权计算,模拟光照斜射产生的明暗对比。关键点在于卷积核要体现“方向性边缘增强”:
- 典型浮雕核是
[1, 0, 0, 0, -1, 0, 0, 0, 0]或更常用[2, 0, 0, 0, -1, 0, 0, 0, -1],注意order="3"和preserveAlpha="false" - 必须设
edgeMode="wrap"或"duplicate",否则边缘会发黑/发白 - SVG 滤镜需挂载在
内,再通过的filterCSS 属性或 CanvasdrawImage()绘制带滤镜的 SVG 元素
示例 SVG 片段:
Canvas 手动实现浮雕:用 getImageData() + 灰度 + 差分
若需动态控制或兼容性更强(比如绕过 SVG 滤镜限制),得自己算像素。核心步骤是:灰度化 → X/Y 方向差分 → 合并为单通道明暗 → 映射到 0–255。这不是“调个参数”,而是实打实的像素遍历:
立即学习“前端免费学习笔记(深入)”;
- 灰度公式推荐用亮度法:
0.299*r + 0.587*g + 0.114*b,比平均值更准 - 差分用 Sobel 算子比简单减法更稳:
sx = (r[-1,-1]+2*r[0,-1]+r[1,-1]) - (r[-1,1]+2*r[0,1]+r[1,1]) - 最终输出 =
128 + 0.5*sx + 0.5*sy,避免溢出要Math.max(0, Math.min(255, ...)) - 注意:Canvas 跨域图片会触发
SecurityError,务必确保图片同源或已设置crossOrigin="anonymous"
CSS filter: url(#emboss) 的坑
这个写法看似简洁,但实际踩点极多:
-
url(#emboss)必须指向同文档内的 SVG,外链 SVG 不生效(CSP 和 CORS 双重限制) - Firefox 对
feConvolveMatrix的bias支持不稳定,建议固定设为bias="128"并配合div容器的background-color: #808080做底色补偿 - 滤镜作用于整个元素,无法只对图片局部浮雕;若需局部效果,得用 Canvas 截图 + 裁剪 + 滤镜 + 贴回
浮雕不是开关式效果,它依赖光源方向感和对比度平衡,bias、kernelMatrix、edgeMode 三个参数稍调就容易变“浮肿”或“塌陷”,动手前先拿 PS 试好核矩阵再搬代码。










