feTurbulence本身不输出可见纹理,因其默认type="turbulence"生成不可见位移向量,type="fractalNoise"输出的[0,1]灰度易被截断,且必须配合feColorMatrix、feComposite等滤镜并指定result才能显形。

feTurbulence 本身不输出可见纹理,直接用它填充背景只会看到一片黑或灰——这不是 bug,是设计如此。
为什么 feTurbulence 单独写没效果
常见错误是只写:<feTurbulence type="fractalNoise" baseFrequency="0.05"/>。这不会在页面上显示任何东西,原因有三:
-
type="turbulence"(默认)输出的是位移向量,不是颜色值,result输出不可见 -
type="fractalNoise"虽输出灰度,但默认范围是[0,1],在多数滤镜链中会被截断或混入透明通道而不可见 - 没指定
result属性,后续节点无法引用;也没把它传给可渲染的滤镜(如feColorMatrix或feComposite)
baseFrequency 和 numOctaves 怎么设才像自然纹理
这两个参数决定噪声的“物理尺度感”。设错就会像马赛克或水波纹,而不是云、雾、纸纹:
-
baseFrequency控制主频尺寸:胶片颗粒用0.002 0.003,云朵用0.01 0.02,粗纸纹用0.04 0.06;两个值不等(如"0.045 0.038")能制造各向异性,更自然 -
numOctaves决定层次丰富度:设为1看起来单薄平滑;2是通用甜点值;3+在 Safari 和低端 Android 上易卡顿,且可能过载细节 - 必须加
stitchTiles="stitch",否则大块背景边缘会出现明显接缝(尤其用background-size: cover时)
怎么把噪声变成可见的纹理层
核心思路:把 feTurbulence 的输出转成可控灰度图,再混合到颜色层。三步不能少:
立即学习“前端免费学习笔记(深入)”;
- 用
feColorMatrix把噪声转成高对比灰度:values="0.33 0.33 0.33 0 0"(Luminance 转换),再通过k4偏移和k3缩放控制明暗范围 - 用
feComposite operator="arithmetic" k1="0" k2="1" k3="1" k4="0"实现线性叠加,比multiply或screen更稳定,不依赖背景色明暗 - 滤镜必须作用于
background-image层,而非整个元素——用background-image: url("data:image/svg+xml,...")内联方式,确保只扰动背景,不模糊文字或边框
Safari 兼容性和隐藏陷阱
真实项目里最容易翻车的地方不在参数调优,而在浏览器实现差异:
- Safari 对
numOctaves > 2和非零seed支持差,应固定seed="0" -
<svg>必须设width="0" height="0" style="display:none",否则可能触发意外 layout 重排 -
feTurbulence不可用于 Canvas 2D:ctx.filter = "url(#noise)"在 Chrome/Firefox 下静默失效,在 Safari 下可能报错或完全无反应 - 别用
filter: url(#noise)直接套在容器上——它会把文字、图标、阴影全送进滤镜管线,导致点击反馈变慢、边缘糊掉



















