给一个圆添加柔和的投影?让一张图片变成黑白?制作一个毛玻璃效果的卡片?或者让文字像水面一样波动?

在 CSS 里,你可能需要 box-shadow、filter 或 backdrop-filter。但当效果变得更复杂——比如方向性阴影、颜色矩阵变换、甚至流体扭曲——CSS 就显得力不从心了。

这时候,SVG 滤镜就该登场了。

SVG 滤镜就像一套“图形特效处理器”。它由多个可组合的“效果单元”(官方叫滤镜基元,filter primitives)串联而成,每个单元负责一种特定的图像处理——模糊、偏移、颜色变换、扭曲……你可以像搭积木一样把它们拼在一起,创造出 CSS 无法实现的视觉效果。

这篇文章会从零开始,带你理解 SVG 滤镜的工作方式,掌握最常用的几个滤镜基元,最后用一个综合案例把它们串起来。

一、滤镜是什么?先看一个最简单的例子

在 SVG 里,滤镜通过 <filter> 元素定义,通常放在 <defs> 区块中。定义好之后,用 filter="url(#滤镜ID)" 把它“贴”到目标图形上。

来看一个最基础的模糊效果:

<svg width="230" height="120" xmlns="http://www.w3.org/2000/svg">
  <!-- 1. 在 defs 中定义滤镜 -->
  <defs>
    <filter id="blurMe">
      <feGaussianBlur in="SourceGraphic" stdDeviation="5" />
    </filter>
  </defs>
  
  <!-- 2. 左边是不加滤镜的圆(参照物) -->
  <circle cx="60" cy="60" r="50" fill="green" />
  
  <!-- 3. 右边是加了滤镜的圆 -->
  <circle cx="170" cy="60" r="50" fill="green" filter="url(#blurMe)" />
</svg>

代码很简单,但包含了 SVG 滤镜的三个核心要素:

  1. <filter>:滤镜的“容器”,用 id 给它起个名字。

  2. 滤镜基元:这里用的是 <feGaussianBlur>,负责执行“高斯模糊”这个具体操作。

  3. filter 属性:在目标元素上通过 url(#id) 引用滤镜。

in="SourceGraphic" 是什么意思?

每个滤镜基元都需要一个“输入”。SourceGraphic 表示“原始图形本身”——也就是那个绿色的圆。基元对输入做处理,然后输出结果。后面你会看到,一个基元的输出可以成为下一个基元的输入,这就是“串联”的秘密。

二、滤镜的“边界盒子”:为什么效果被裁剪了?

先停一下,说一个新手最容易遇到的坑。

有时候你给图形加了投影或模糊,发现效果被裁掉了一半——阴影只显示了一小块,模糊的边缘像被剪刀剪过一样整齐。

这是因为 <filter> 默认的作用区域是“目标元素的边界框”(filterUnits="objectBoundingBox"),而模糊或偏移产生的效果会超出这个边界框。

解决方案:手动扩大滤镜的作用区域。

<svg width="230" height="120" xmlns="http://www.w3.org/2000/svg">
    <defs>
        <!--
          x/y/width/height 扩大滤镜区域:
          阴影向外扩散时不会被裁切
        -->
        <filter id="dropShadow" x="-20%" y="-20%" width="140%" height="140%">
            <!-- 1. 对图形的 Alpha 通道做模糊,得到软边阴影 -->
            <feGaussianBlur in="SourceAlpha" stdDeviation="5" result="blur" />
            <!-- 2. 将模糊结果偏移,形成落影位置 -->
            <feOffset in="blur" dx="6" dy="6" result="offsetBlur" />
            <!-- 3. 先画阴影,再叠回原图 -->
            <feMerge>
                <feMergeNode in="offsetBlur" />
                <feMergeNode in="SourceGraphic" />
            </feMerge>
        </filter>
    </defs>

    <!-- 左边:不加滤镜的参照 -->
    <circle cx="60" cy="55" r="40" fill="#3498db" />

    <!-- 右边:应用 dropShadow -->
    <circle cx="170" cy="55" r="40" fill="#3498db" filter="url(#dropShadow)" />
</svg>

x、y、width、height 定义了滤镜的“画布”大小。这里把左上角向左上各扩展 20%,宽高各放大到 140%,给模糊和阴影留出足够的“呼吸空间”。

经验法则:凡是涉及 feGaussianBlur(模糊)或 feOffset(偏移)的滤镜,都顺手把 filter 的边界扩大一些,能省去很多排查时间。

filterUnits 的两种模式:

  • objectBoundingBox(默认):x/y/width/height 是元素边界框的百分比或分数。灵活但不够直观。

  • userSpaceOnUse:x/y/width/height 使用当前用户坐标系的像素值,通常就是 SVG 视口的像素。更直观可控。

三、常用的滤镜基元:你的“特效工具箱”

SVG 提供了大约 20 种滤镜基元。对初中级开发者来说,掌握下面这 6 个,就能覆盖 90% 以上的日常需求。

fe = Filter Effect(滤镜效果)

SVG 滤镜原语都用 fe 前缀,表示它们是滤镜效果元素,例如:

  • feGaussianBlur — 高斯模糊滤镜效果

  • feOffset — 偏移滤镜效果

  • feMerge / feMergeNode — 合并滤镜效果

3.1 <feGaussianBlur> —— 高斯模糊

作用:让图形变模糊,产生“柔焦”效果。

<feGaussianBlur in="SourceGraphic" stdDeviation="5" />
  • stdDeviation:模糊强度,数值越大越模糊。可以写两个值(如 "5 10"),分别控制水平和垂直方向的模糊程度。

典型用途:制作阴影的“模糊层”、毛玻璃效果、背景虚化。

3.2 <feOffset> —— 位移

作用:把图像沿 x 轴和 y 轴方向平移。

<feOffset in="blur" dx="4" dy="4" result="offsetBlur" />
  • dx / dy:水平和垂直偏移量(正数向右/向下)。

典型用途:配合模糊制作投影——先把原图模糊,再偏移,就得到了阴影的“形状”。

3.3 <feMerge> —— 合并图层

作用:把多个图像“叠”在一起。

<feMerge>
  <feMergeNode in="offsetBlur" />
  <feMergeNode in="SourceGraphic" />
</feMerge>

<feMerge> 里面可以放多个 <feMergeNode>, 先写的在底层,后写的在上层。上面的例子中,offsetBlur(阴影)在下面,SourceGraphic(原始图形)在上面——正好形成一个“投影在底下、原图在上面”的层次关系。

典型用途:把原始图形和它的阴影、发光等效果合成在一起。

3.4 <feColorMatrix> —— 颜色矩阵变换

作用:对每个像素的颜色做矩阵乘法,实现色相旋转、饱和度调整、灰度化、颜色替换等效果。

<!-- 把彩色图片变成黑白 -->
<feColorMatrix type="saturate" values="0" />

<!-- 色相旋转 180° -->
<feColorMatrix type="hueRotate" values="180" />

<!-- 反色(自定义 4×5 矩阵)-->
<feColorMatrix type="matrix" values="
  -1 0 0 0 1
   0 -1 0 0 1
   0 0 -1 0 1
   0 0 0 1 0"/>

  • type="saturate":饱和度控制,values="0" 就是完全黑白。

  • type="hueRotate":色相旋转,角度 0~360。

  • type="matrix":最强大的模式,用 4×5 矩阵自定义颜色变换。每一行对应输出的 R/G/B/A,每一列对应输入的 R/G/B/A 和一个常数偏移。

质感提示:type="matrix" 的 4×5 矩阵看似可怕,其实规律很简单。第一行决定新红色怎么算,第二行决定新绿色……最后一列是常数偏移。复古色调(Sepia)的矩阵不是魔法,而是前人总结的经验值。实际开发中可以用在线工具实时调整矩阵参数。

典型用途:图片滤镜(黑白、复古)、图标颜色动态替换、特殊色调效果。

完整示例

<div class="row">
    <figure>
        <svg width="160" height="140" xmlns="http://www.w3.org/2000/svg">
            <circle cx="50" cy="70" r="36" fill="#e74c3c" />
            <circle cx="80" cy="70" r="36" fill="#2ecc71" />
            <circle cx="110" cy="70" r="36" fill="#3498db" />
        </svg>
        <figcaption>原图(无滤镜)</figcaption>
    </figure>

    <figure>
        <svg width="160" height="140" xmlns="http://www.w3.org/2000/svg">
            <defs>
                <filter id="toGray">
                    <!-- 把彩色图片变成黑白 -->
                    <feColorMatrix type="saturate" values="0" />
                </filter>
            </defs>
            <g filter="url(#toGray)">
                <circle cx="50" cy="70" r="36" fill="#e74c3c" />
                <circle cx="80" cy="70" r="36" fill="#2ecc71" />
                <circle cx="110" cy="70" r="36" fill="#3498db" />
            </g>
        </svg>
        <figcaption>saturate=0(去饱和 / 黑白)</figcaption>
    </figure>

    <figure>
        <svg width="160" height="140" xmlns="http://www.w3.org/2000/svg">
            <defs>
                <filter id="hueFlip">
                    <!-- 色相旋转 180° -->
                    <feColorMatrix type="hueRotate" values="180" />
                </filter>
            </defs>
            <g filter="url(#hueFlip)">
                <circle cx="50" cy="70" r="36" fill="#e74c3c" />
                <circle cx="80" cy="70" r="36" fill="#2ecc71" />
                <circle cx="110" cy="70" r="36" fill="#3498db" />
            </g>
        </svg>
        <figcaption>hueRotate=180(互补色)</figcaption>
    </figure>

    <figure>
        <svg width="160" height="140" xmlns="http://www.w3.org/2000/svg">
            <defs>
                <filter id="invert">
                    <!-- 反色(自定义 4×5 矩阵)-->
                    <feColorMatrix type="matrix" values="
                    -1 0 0 0 1
                    0 -1 0 0 1
                    0 0 -1 0 1
                    0 0 0 1 0"/>
                </filter>
            </defs>
            <g filter="url(#invert)">
                <circle cx="50" cy="70" r="36" fill="#e74c3c" />
                <circle cx="80" cy="70" r="36" fill="#2ecc71" />
                <circle cx="110" cy="70" r="36" fill="#3498db" />
            </g>
        </svg>
        <figcaption>matrix 反色(RGB 取反)</figcaption>
    </figure>
</div>

3.5 <feTurbulence> —— 噪声/湍流

作用:用 Perlin 噪声算法生成“随机纹理”——像云雾、大理石、水波纹一样的自然图案。

<feTurbulence type="turbulence" baseFrequency="0.05" numOctaves="2" result="turbulence" />
  • type:turbulence(湍流,更激烈)或 fractalNoise(分形噪声,更平滑)。

  • baseFrequency:噪声的“频率”,值越小纹理越平滑、越大越细碎。可以写两个值分别控制 x/y 方向。

  • numOctaves:噪声的“细节层次”,值越大纹理越丰富(但计算量也越大)。

技术细节:baseFrequency 可以理解为"缩放级别",numOctaves 是"细节滑块"。baseFrequency=0.01 是宏观的云层,0.1 就变成细碎的颗粒噪点了。在性能敏感场景下,numOctaves 不要超过 3,否则会明显影响渲染性能。

典型用途:生成云朵、火焰、水波纹、大理石纹理等有机效果。

大理石纹理示例:

<figure>
    <svg width="320" height="220" xmlns="http://www.w3.org/2000/svg">
        <defs>
            <filter id="marble" x="0" y="0" width="100%" height="100%" color-interpolation-filters="sRGB">
                <!-- Perlin 湍流噪声:baseFrequency 越小纹理越大,numOctaves 越大层次越丰富 -->
                <feTurbulence type="turbulence" baseFrequency="0.05" numOctaves="2" seed="7" result="turbulence" />
                <!-- 把 RGB 噪声压成灰阶,露出深浅相间的天然条纹 -->
                <feColorMatrix in="turbulence" type="saturate" values="0" result="grayNoise" />
                <!-- 提高对比,让“矿脉”更清晰 -->
                <feComponentTransfer in="grayNoise" result="veins">
                    <feFuncR type="gamma" amplitude="1" exponent="0.55" offset="0" />
                    <feFuncG type="gamma" amplitude="1" exponent="0.55" offset="0" />
                    <feFuncB type="gamma" amplitude="1" exponent="0.55" offset="0" />
                </feComponentTransfer>
                <!-- 映射成大理石色:浅底 + 青灰/墨色纹理 -->
                <feColorMatrix in="veins" type="matrix" values="
                    0.55 0.20 0.10 0 0.38
                    0.48 0.22 0.10 0 0.34
                    0.42 0.18 0.12 0 0.30
                    0    0    0    1 0" />
            </filter>
        </defs>
        <rect width="320" height="220" rx="8" filter="url(#marble)" />
    </svg>
    <figcaption>矩形表面:大理石纹理</figcaption>
</figure>

3.6 <feDisplacementMap> —— 位移映射

作用:根据另一张图(in2)的像素值,把当前图(in)的像素“挤来挤去”,产生扭曲变形。

<feDisplacementMap in="SourceGraphic" in2="turbulence" scale="50" 
                   xChannelSelector="R" yChannelSelector="G" />

  • in2:用作“位移地图”的图像(通常来自 feTurbulence)。

  • scale:位移强度,数值越大变形越剧烈。

  • xChannelSelector / yChannelSelector:用 in2 的哪个颜色通道来控制 x/y 方向的位移。

常见坑提示:in2 必须指向一个存在的 result。如果 feTurbulence 的 result="noise",那么 feDisplacementMap 的 in2 就必须是 "noise"。写错了滤镜会静默失败,很难调试。

典型用途:水波纹、液体扭曲、文字液化、玻璃折射效果。

湍流示例:

<figure>
    <svg width="280" height="180" xmlns="http://www.w3.org/2000/svg">
        <defs>
            <linearGradient id="bars2" x1="0" y1="0" x2="1" y2="0">
                <stop offset="0%" stop-color="#e74c3c" />
                <stop offset="25%" stop-color="#f1c40f" />
                <stop offset="50%" stop-color="#2ecc71" />
                <stop offset="75%" stop-color="#3498db" />
                <stop offset="100%" stop-color="#9b59b6" />
            </linearGradient>
            <filter id="displace" x="-20%" y="-20%" width="140%" height="140%">
                <!-- 生成 Perlin 噪声,result 名称供下一步 in2 引用 -->
                <feTurbulence type="turbulence" baseFrequency="0.02" numOctaves="3" seed="2" result="turbulence" />
                <!-- 用噪声的 R/G 通道分别推开原图的 X/Y 像素 -->
                <feDisplacementMap in="SourceGraphic" in2="turbulence" scale="50"
                                   xChannelSelector="R" yChannelSelector="G" />
            </filter>
        </defs>
        <g filter="url(#displace)">
            <rect width="280" height="180" fill="url(#bars2)" />
            <text x="140" y="105" text-anchor="middle" font-size="56" font-weight="700" fill="#fff">SVG</text>
        </g>
    </svg>
    <figcaption>feTurbulence + feDisplacementMap(scale=50)</figcaption>
</figure>

四、组合的艺术:把基元串起来

单个滤镜基元的效果有限。真正的威力来自于把它们串联起来——一个基元的输出成为下一个基元的输入。

这里的关键是 result 和 in 属性:

  • result:给当前基元的输出起个名字。

  • in:指定当前基元的输入来源(可以是 SourceGraphic、SourceAlpha,或者前面某个基元的 result)。

案例一:手动打造投影效果

虽然 SVG 有专门的 <feDropShadow> 元素,但理解手动实现的过程能帮你真正掌握“串联”的思路:

<filter id="manualShadow" x="-20%" y="-20%" width="140%" height="140%">
  <!-- 第1步:提取图形的透明度通道,生成模糊 -->
  <feGaussianBlur in="SourceAlpha" stdDeviation="4" result="blur" />
  <!-- 第2步:把模糊结果向右下偏移 -->
  <feOffset in="blur" dx="4" dy="4" result="offsetBlur" />
  <!-- 第3步:把阴影和原始图形叠在一起 -->
  <feMerge>
    <feMergeNode in="offsetBlur" />
    <feMergeNode in="SourceGraphic" />
  </feMerge>
</filter>

流程图:

原始图形 → 提取透明度通道 → 模糊 → 偏移 → 和原始图形合并 → 最终效果

注意这里用的是 SourceAlpha(图形的透明度通道)而不是 SourceGraphic(完整图形)。为什么?因为阴影只需要“形状”,不需要颜色。用透明度通道生成的阴影是纯黑轮廓,后续可以任意着色。

案例二:发光效果(Glow)

把上面的投影改一改——不偏移,直接叠加,就变成了发光效果:

<figure>
    <svg width="280" height="180" xmlns="http://www.w3.org/2000/svg">
        <defs>
            <filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
                <!-- 生成模糊的发光层 -->
                <feGaussianBlur in="SourceGraphic" stdDeviation="6" result="blur" />
                <!-- 把原图和发光层叠加 -->
                <feMerge>
                    <feMergeNode in="blur" />
                    <feMergeNode in="SourceGraphic" />
                </feMerge>
            </filter>
        </defs>
        <rect width="280" height="180" fill="#11141a" rx="8" />
        <g filter="url(#glow)">
            <circle cx="80" cy="90" r="36" fill="#00e5ff" />
            <text x="180" y="102" text-anchor="middle" font-size="36" font-weight="700" fill="#fff">GLOW</text>
        </g>
    </svg>
    <figcaption>feGaussianBlur + feMerge(stdDeviation=6)</figcaption>
</figure>

注意这里把滤镜边界扩大到 200%,因为发光效果需要更多的"呼吸空间"。如果想改变发光的颜色,可以在模糊之后加一个 <feColorMatrix> 或 <feFlood> 来着色。

五、综合案例:水波纹扭曲效果

现在把前面学的几个基元组合起来,做一个“文字在水面波动”的效果:

<svg width="400" height="200" viewBox="0 0 400 200" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <!-- 水波纹滤镜 -->
    <filter id="waterRipple" x="-20%" y="-20%" width="140%" height="140%">
      <!-- 1. 生成噪声纹理 -->
      <feTurbulence type="turbulence" baseFrequency="0.02 0.06" 
                    numOctaves="3" result="noise" />
      <!-- 2. 用噪声纹理扭曲文字 -->
      <feDisplacementMap in="SourceGraphic" in2="noise" 
                         scale="20" xChannelSelector="R" yChannelSelector="G" />
    </filter>
  </defs>
  
  <!-- 应用滤镜的文字 -->
  <text x="200" y="120" font-size="48" font-weight="bold" 
        fill="#1a73e8" text-anchor="middle" filter="url(#waterRipple)">
    波 动
  </text>
</svg>

原理拆解:

  1. <feTurbulence> 生成一个随机噪声图。

  2. <feDisplacementMap> 用这个噪声图“推挤”文字的每个像素。

  3. baseFrequency="0.02 0.06" 让水平方向波纹更宽、垂直方向更密,模拟真实水面的涟漪。

  4. scale="20" 控制扭曲强度。

如果把这个效果做成动画——让 baseFrequency 或 scale 随时间变化——就能得到流动的水面效果。

六、在 CSS 中使用 SVG 滤镜

SVG 滤镜不只属于 SVG 图形。你可以把它应用到任何 HTML 元素上,通过 CSS 的 filter 属性引用:

<!-- 在 HTML 中定义 SVG 滤镜(隐藏起来) -->
<svg width="0" height="0" aria-hidden="true">
  <defs>
    <filter id="glassEffect">
      <feGaussianBlur in="SourceGraphic" stdDeviation="8" />
    </filter>
  </defs>
</svg>

<!-- 在 CSS 中应用到任意元素 -->
<style>
  .card {
    filter: url(#glassEffect);
  }
</style>

<!-- 使用 -->
<div class="card">毛玻璃卡片</div>

注意事项:

  • 为了让隐藏的 <svg> 不影响布局,可以设置 width="0" height="0" 并用 position: fixed 把它移出文档流。

  • SVG 滤镜可以和 CSS 滤镜 链式使用:filter: url(#myFilter) blur(2px)。

  • 涉及颜色运算的滤镜,建议加上 color-interpolation-filters="sRGB",以保证跨浏览器效果一致。

  • SVG 滤镜在现代浏览器中支持良好(Chrome 53+、Firefox 35+、Safari 10.1+、Edge 79+),但复杂滤镜在 Safari 中性能较差。

七、性能优化:用得起还得用得好

SVG 滤镜的本质是像素级运算——浏览器需要先把矢量图形光栅化为临时位图,再对每个像素做数学变换。这意味着复杂滤镜是”性能重灾区“,不当地使用会严重拖慢页面帧率。

7.1 能用 CSS 滤镜的,就别用 SVG

CSS 的 filter 属性(blur()、grayscale()、drop-shadow()、backdrop-filter 等)由浏览器厂商高度优化,通常跑在 GPU 上。对于简单模糊、灰度、投影,优先用 CSS。

<!-- 推荐:CSS 简洁高效 -->
.blurred  { filter: blur(5px); }
.gray     { filter: grayscale(100%); }
.shadowed { filter: drop-shadow(0 4px 8px rgba(0,0,0,.3)); }

<!-- 仅当 CSS 做不到时,再用 SVG 滤镜 -->
7.2 严格收缩滤镜作用域

这是性能优化中投入产出比最高的一项。默认情况下,滤镜可能会处理整个 SVG 视口的像素,而不是仅应用滤镜的那个元素。通过明确设置 x/y/width/height,可减少 50%~80% 的像素处理量。

7.3 避免动画 stdDeviation

动态修改 feGaussianBlur 的 stdDeviation 会强制浏览器在每一帧重新计算模糊矩阵,代价极大。如果需要”脉动发光“效果,更好的做法是预渲染一个静态模糊层,再用 CSS 动画控制 opacity 或 transform: scale()。

7.4 性能开销对照表

滤镜基元

性能开销

优化建议

feColorMatrix

低

随意使用,开销很小

feMerge / feOffset

低

轻量操作,可放心使用

feGaussianBlur

中

stdDev 不超过 8,不动画

feDropShadow

中

优先用 CSS drop-shadow()

feTurbulence

高

numOctaves≤3,限制区域

feDisplacementMap

高

配合限制区域使用

7.5 其他实用建议
  • 颜色空间:非必要时用 color-interpolation-filters="sRGB",减少线性 RGB 转换开销。

  • 合并顺序:把模糊等重资源操作放在链路尽可能晚的位置,先处理小区域再合成。

  • 缓存静态滤镜:不变滤镜定义一次,多处引用,避免重复计算。

  • will-change 提示:对动画元素用 will-change: filter 提示浏览器预分配缓冲。

八、进阶技巧:从会用到用得好

8.1 双色调(Duotone)效果

双色调是当下流行的设计风格,可用 feColorMatrix 的 matrix 模式精确实现:

<!-- 把图像映射到蓝紫双色调 -->
<filter id="duotone">
  <feColorMatrix type="matrix" values="
    0.2 0.6 0.1 0 0.1
    0.1 0.3 0.5 0 0.0
    0.4 0.2 0.4 0 0.2
    0   0   0   1 0"/>
</filter>

原理是先通过矩阵第一行做灰度加权(R、G、B 通道按不同权重混合),再把灰度值映射到目标颜色空间。这种技术适用于平面设计、专辑封面、专题页面等场景。

8.2 模拟色觉障碍(无障碍设计)

前端环境已支持用 SVG 滤镜模拟色觉障碍(如红色盲 Deuteranopia)。通过精确的 feColorMatrix 矩阵,可以在页面顶层覆盖一层”滤镜”,实时预览不同色觉能力用户看到的效果。

<!-- 模拟绿色盲(Deuteranopia) -->
<svg style="position:fixed;width:0;height:0">
  <filter id="deuteranopia">
    <feColorMatrix values="
      0.367  0.861 -0.228  0  0
      0.280  0.673  0.047  0  0
     -0.012  0.043  0.969  0  0
      0       0      0     1  0"/>
  </filter>
</svg>
<style>:root { filter: url(#deuteranopia); }</style>
8.3 动态滤镜参数(JavaScript 控制)

用 JavaScript 动态修改滤镜属性,可以实现交互式效果:

// 让噪声「呼吸」——模拟水面流动
const turbulence = document.querySelector('feTurbulence');
let frame = 0;
function animate() {
  frame++;
  const freq = 0.04 + Math.sin(frame * 0.01) * 0.02;
  turbulence.setAttribute('baseFrequency', freq);
  requestAnimationFrame(animate);
}
animate();

性能提示:动画时把幅度控制在较小范围(如 ±0.02),不要让 baseFrequency 大幅变化。幅度太大会让重绘开销暴增,容易卡顿。

九、常见场景速查表

想要的效果

用什么基元组合

备注

投影

feGaussianBlur + feOffset + feMerge

或用 feDropShadow 替代

发光

feGaussianBlur + feMerge

可加 feFood 着色

 黑白/复古

feColorMatrix type="saturate" values="0"

matrix 模式更灵活

毛玻璃

feGaussianBlur(配合背景)

CSS backdrop-filter 更优

水波纹/扭曲

feTurbulence + feDisplacementMap

注意性能开销

云朵/纹理

feTurbulence(单独使用或配合着色)

fractalNoise 更平滑

颜色替换

feColorMatrix type="matrix"

需计算 4 × 5 矩阵

内阴影

feOffset + feComposite operator="in"

高级技巧,需多步链路

十、总结

知识点

一句话总结

<filter>

镜的容器,用 id 标识,放在 <defs> 中

滤镜基元

每个基元负责一种具体处理(模糊、偏移、颜色变换等)

in / result

基元的输入输出,用于串联多个基元

feGaussianBlur

高斯模糊,制作阴影和发光的基础

feOffset

位移,控制阴影的方向和距离

feMerge

图层叠加,把多个结果合成一张图

feColorMatrix

颜色矩阵,实现黑白、色相旋转等

feTurbulence

噪声生成,制作云、水、纹理等自然效果

feDisplacementMap

位移映射,实现扭曲和波纹

滤镜边界

记得扩大 x/y/width/height,防止效果被裁剪

性能策略

能用 CSS 滤镜的优先 CSS;SVG 留给 CSS 做不到的效果

核心心法:

SVG 滤镜的本质是图像处理流水线。你把原始图形送进流水线,经过一道道“工序”(滤镜基元),每一道工序都在修改像素的颜色或位置,最后输出成品。

掌握这个“流水线思维”,你就能把任何复杂的视觉效果拆解成一系列可组合的步骤——先用 feTurbulence 生成噪声,再用 feDisplacementMap 扭曲,再用 feColorMatrix 调色,最后用 feMerge 合成…… 就像在代码里用 Photoshop 一样。