pin_drop当前位置:知识文库 ❯ 图文

多媒体:SVG滤镜 - 完整教程与代码示例

一、教程简介

SVG 滤镜是对图形元素应用视觉效果的强大机制。通过 <filter> 元素和各种滤镜原语(filter primitives),可以实现模糊、阴影、光照、色彩变换、形态学操作等各种效果。本教程将详细讲解 SVG 滤镜的创建、常用滤镜原语的使用和实际应用。


二、核心概念

filter 元素

滤镜定义在 <defs> 中的 <filter> 元素内,通过 filter="url(#id)" 引用。

滤镜原语

每个滤镜原语以 fe 开头,代表一个图像处理操作。多个原语可以串联使用。

滤镜区域

代码示例

<filter id="myFilter" x="-10%" y="-10%" width="120%" height="120%">
  <!-- 滤镜原语 -->
</filter>
属性 说明 默认值
x, y 滤镜区域起点 -10%
width, height 滤镜区域大小 120%
filterUnits 区域坐标系统 objectBoundingBox

三、语法与用法

常用滤镜原语

原语 说明
feGaussianBlur 高斯模糊
feDropShadow 投影阴影
feOffset 偏移
feColorMatrix 颜色矩阵变换
feBlend 混合模式
feMerge 合并图层
feFlood 填充颜色
feComposite 合成操作
feTurbulence 噪声/纹理
feDisplacementMap 位移映射
feMorphology 形态学操作(膨胀/腐蚀)
feConvolveMatrix 卷积矩阵
feSpecularLighting 镜面光照
feDiffuseLighting 漫反射光照

四、代码示例

示例1:常用滤镜效果演示

代码示例

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>SVG 滤镜效果演示</title>
  <style>
    body {
      margin: 0; padding: 20px;
      background: #0d1117; color: #c9d1d9;
      font-family: 'Segoe UI', sans-serif;
      display: flex; flex-direction: column; align-items: center;
    }
    .grid {
      display: grid; grid-template-columns: repeat(3, 1fr);
      gap: 15px; max-width: 750px;
    }
    .card {
      background: #161b22; border: 1px solid #30363d;
      border-radius: 8px; padding: 12px; text-align: center;
    }
    .card h3 { color: #58a6ff; font-size: 13px; margin: 0 0 8px; }
    svg { background: #0d1117; border-radius: 4px; }
  </style>
</head>
<body>
  <h1>SVG 滤镜效果演示</h1>
  <div class="grid">
    <!-- 高斯模糊 -->
    <div class="card">
      <h3>feGaussianBlur 模糊</h3>
      <svg width="220" height="120" viewBox="0 0 220 120">
        <defs>
          <filter id="blur1">
            <feGaussianBlur in="SourceGraphic" stdDeviation="3" />
          </filter>
        </defs>
        <text x="110" y="30" text-anchor="middle" font-size="12" fill="#8b949e">原图</text>
        <circle cx="70" cy="70" r="25" fill="#e94560" />
        <circle cx="110" cy="70" r="25" fill="#58a6ff" />
        <circle cx="90" cy="55" r="25" fill="#3fb950" opacity="0.7" />

        <text x="110" y="115" text-anchor="middle" font-size="10" fill="#8b949e">模糊后</text>
        <g filter="url(#blur1)" transform="translate(0,-5)">
          <circle cx="70" cy="70" r="25" fill="#e94560" />
          <circle cx="110" cy="70" r="25" fill="#58a6ff" />
          <circle cx="90" cy="55" r="25" fill="#3fb950" opacity="0.7" />
        </g>
      </svg>
    </div>

    <!-- 投影阴影 -->
    <div class="card">
      <h3>feDropShadow 阴影</h3>
      <svg width="220" height="120" viewBox="0 0 220 120">
        <defs>
          <filter id="shadow1">
            <feDropShadow dx="3" dy="3" stdDeviation="3" flood-color="#000" flood-opacity="0.5" />
          </filter>
        </defs>
        <rect x="30" y="25" width="70" height="70" rx="10" fill="#58a6ff" filter="url(#shadow1)" />
        <circle cx="160" cy="60" r="35" fill="#e94560" filter="url(#shadow1)" />
      </svg>
    </div>

    <!-- 颜色矩阵 -->
    <div class="card">
      <h3>feColorMatrix 灰度</h3>
      <svg width="220" height="120" viewBox="0 0 220 120">
        <defs>
          <filter id="gray1">
            <feColorMatrix type="saturate" values="0" />
          </filter>
        </defs>
        <rect x="20" y="20" width="80" height="80" rx="8" fill="#e94560" />
        <rect x="120" y="20" width="80" height="80" rx="8" fill="#e94560" filter="url(#gray1)" />
        <text x="60" y="110" text-anchor="middle" font-size="10" fill="#8b949e">原图</text>
        <text x="160" y="110" text-anchor="middle" font-size="10" fill="#8b949e">灰度</text>
      </svg>
    </div>

    <!-- 噪声纹理 -->
    <div class="card">
      <h3>feTurbulence 噪声</h3>
      <svg width="220" height="120" viewBox="0 0 220 120">
        <defs>
          <filter id="turb1">
            <feTurbulence type="fractalNoise" baseFrequency="0.05" numOctaves="3" />
          </filter>
          <filter id="turb2">
            <feTurbulence type="turbulence" baseFrequency="0.02" numOctaves="2" />
          </filter>
        </defs>
        <rect x="10" y="10" width="95" height="100" rx="4" filter="url(#turb1)" />
        <rect x="115" y="10" width="95" height="100" rx="4" filter="url(#turb2)" />
        <text x="57" y="118" text-anchor="middle" font-size="9" fill="#8b949e">fractalNoise</text>
        <text x="162" y="118" text-anchor="middle" font-size="9" fill="#8b949e">turbulence</text>
      </svg>
    </div>

    <!-- 形态学 -->
    <div class="card">
      <h3>feMorphology 膨胀/腐蚀</h3>
      <svg width="220" height="120" viewBox="0 0 220 120">
        <defs>
          <filter id="dilate1">
            <feMorphology operator="dilate" radius="2" />
          </filter>
          <filter id="erode1">
            <feMorphology operator="erode" radius="1" />
          </filter>
        </defs>
        <text x="37" y="40" text-anchor="middle" font-size="22" font-weight="bold" fill="#58a6ff">SVG</text>
        <text x="110" y="40" text-anchor="middle" font-size="22" font-weight="bold" fill="#58a6ff" filter="url(#dilate1)">SVG</text>
        <text x="183" y="40" text-anchor="middle" font-size="22" font-weight="bold" fill="#58a6ff" filter="url(#erode1)">SVG</text>
        <text x="37" y="60" text-anchor="middle" font-size="9" fill="#8b949e">原图</text>
        <text x="110" y="60" text-anchor="middle" font-size="9" fill="#8b949e">膨胀</text>
        <text x="183" y="60" text-anchor="middle" font-size="9" fill="#8b949e">腐蚀</text>

        <rect x="20" y="75" width="55" height="30" rx="4" fill="none" stroke="#3fb950" stroke-width="2" />
        <rect x="82" y="75" width="55" height="30" rx="4" fill="none" stroke="#3fb950" stroke-width="2" filter="url(#dilate1)" />
        <rect x="145" y="75" width="55" height="30" rx="4" fill="none" stroke="#3fb950" stroke-width="2" filter="url(#erode1)" />
      </svg>
    </div>

    <!-- 发光效果 -->
    <div class="card">
      <h3>发光效果 (Blur+Merge)</h3>
      <svg width="220" height="120" viewBox="0 0 220 120">
        <defs>
          <filter id="glow1" x="-50%" y="-50%" width="200%" height="200%">
            <feGaussianBlur in="SourceGraphic" stdDeviation="4" result="blur" />
            <feMerge>
              <feMergeNode in="blur" />
              <feMergeNode in="SourceGraphic" />
            </feMerge>
          </filter>
        </defs>
        <text x="110" y="50" text-anchor="middle" font-size="30" font-weight="bold" fill="#58a6ff" filter="url(#glow1)">
          GLOW
        </text>
        <circle cx="70" cy="85" r="15" fill="#e94560" filter="url(#glow1)" />
        <circle cx="110" cy="85" r="15" fill="#3fb950" filter="url(#glow1)" />
        <circle cx="150" cy="85" r="15" fill="#f8b500" filter="url(#glow1)" />
      </svg>
    </div>
  </div>
</body>
</html>

示例2:高级滤镜效果

代码示例

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>高级滤镜效果</title>
  <style>
    body {
      margin: 0; padding: 20px;
      background: #1a1a2e; color: #eee;
      font-family: 'Segoe UI', sans-serif;
      display: flex; flex-direction: column; align-items: center;
    }
    svg { background: #16213e; border-radius: 8px; border: 1px solid #333; }
  </style>
</head>
<body>
  <h1>SVG 高级滤镜效果</h1>
  <svg width="700" height="350" viewBox="0 0 700 350">
    <defs>
      <!-- 内阴影效果 -->
      <filter id="innerShadow" x="-10%" y="-10%" width="120%" height="120%">
        <feComponentTransfer in="SourceAlpha">
          <feFuncA type="table" tableValues="1 0" />
        </feComponentTransfer>
        <feGaussianBlur stdDeviation="3" />
        <feOffset dx="3" dy="3" result="offsetblur" />
        <feFlood flood-color="#000" flood-opacity="0.5" result="color" />
        <feComposite in2="offsetblur" operator="in" />
        <feComposite in2="SourceAlpha" operator="in" />
        <feMerge>
          <feMergeNode in="SourceGraphic" />
          <feMergeNode />
        </feMerge>
      </filter>

      <!-- 浮雕效果 -->
      <filter id="emboss">
        <feConvolveMatrix order="3" kernelMatrix="-2 -1 0 -1 1 1 0 1 2" />
      </filter>

      <!-- 描边效果 -->
      <filter id="outline" x="-5%" y="-5%" width="110%" height="110%">
        <feMorphology in="SourceAlpha" operator="dilate" radius="2" result="dilated" />
        <feFlood flood-color="#e94560" result="color" />
        <feComposite in="color" in2="dilated" operator="in" result="outline" />
        <feMerge>
          <feMergeNode in="outline" />
          <feMergeNode in="SourceGraphic" />
        </feMerge>
      </filter>

      <!-- 水波纹效果 -->
      <filter id="ripple">
        <feTurbulence type="turbulence" baseFrequency="0.01 0.1" numOctaves="1" result="turb">
          <animate attributeName="baseFrequency" values="0.01 0.1;0.02 0.12;0.01 0.1" dur="4s" repeatCount="indefinite" />
        </feTurbulence>
        <feDisplacementMap in="SourceGraphic" in2="turb" scale="8" />
      </filter>
    </defs>

    <!-- 内阴影 -->
    <text x="100" y="30" text-anchor="middle" font-size="12" fill="#58a6ff">内阴影</text>
    <rect x="20" y="40" width="160" height="80" rx="10" fill="#1f2937" filter="url(#innerShadow)" />

    <!-- 浮雕 -->
    <text x="310" y="30" text-anchor="middle" font-size="12" fill="#58a6ff">浮雕</text>
    <g filter="url(#emboss)">
      <rect x="220" y="40" width="80" height="80" rx="8" fill="#58a6ff" />
      <circle cx="360" cy="80" r="35" fill="#3fb950" />
    </g>

    <!-- 描边效果 -->
    <text x="530" y="30" text-anchor="middle" font-size="12" fill="#58a6ff">描边效果</text>
    <text x="530" y="95" text-anchor="middle" font-size="36" font-weight="bold" fill="#58a6ff" filter="url(#outline)">
      OUTLINE
    </text>

    <!-- 水波纹 -->
    <text x="350" y="165" text-anchor="middle" font-size="12" fill="#58a6ff">水波纹动画</text>
    <text x="350" y="230" text-anchor="middle" font-size="42" font-weight="bold" fill="#3fb950" filter="url(#ripple)">
      RIPPLE
    </text>

    <!-- 复合滤镜 -->
    <text x="350" y="290" text-anchor="middle" font-size="12" fill="#58a6ff">复合滤镜(模糊+阴影+发光)</text>
    <defs>
      <filter id="complex" x="-20%" y="-20%" width="140%" height="140%">
        <feGaussianBlur in="SourceAlpha" stdDeviation="5" result="blur" />
        <feOffset in="blur" dx="4" dy="4" result="offsetBlur" />
        <feFlood flood-color="#000" flood-opacity="0.4" result="color" />
        <feComposite in="color" in2="offsetBlur" operator="in" result="shadow" />
        <feGaussianBlur in="SourceGraphic" stdDeviation="2" result="glowBlur" />
        <feMerge>
          <feMergeNode in="shadow" />
          <feMergeNode in="glowBlur" />
          <feMergeNode in="SourceGraphic" />
        </feMerge>
      </filter>
    </defs>
    <rect x="220" y="300" width="120" height="40" rx="20" fill="#58a6ff" filter="url(#complex)" />
    <text x="280" y="325" text-anchor="middle" font-size="14" fill="#fff" filter="url(#complex)">Button</text>

    <circle cx="450" cy="320" r="25" fill="#e94560" filter="url(#complex)" />
    <circle cx="530" cy="320" r="25" fill="#3fb950" filter="url(#complex)" />
    <circle cx="610" cy="320" r="25" fill="#f8b500" filter="url(#complex)" />
  </svg>
</body>
</html>

五、浏览器兼容性

滤镜原语 Chrome Firefox Safari Edge IE
feGaussianBlur 1+ 3+ 3+ 12+ 10+
feDropShadow 25+ 不支持 8+ 12+ 不支持
feColorMatrix 1+ 3+ 3+ 12+ 10+
feTurbulence 1+ 3+ 3+ 12+ 10+
feConvolveMatrix 1+ 3+ 3+ 12+ 不支持

提示feDropShadow 是较新的简写滤镜,Firefox 不支持,可使用 feGaussianBlur + feOffset + feFlood + feComposite 替代。


六、注意事项与最佳实践

1. 滤镜区域要足够大

代码示例

<!-- 模糊和阴影可能超出元素边界,需要扩大滤镜区域 -->
<filter id="myFilter" x="-20%" y="-20%" width="140%" height="140%">

2. 滤镜性能

滤镜计算开销较大,避免在大量元素上同时使用复杂滤镜。

3. feDropShadow 兼容性

代码示例

<!-- 兼容写法(替代 feDropShadow) -->
<filter id="shadow">
  <feGaussianBlur in="SourceAlpha" stdDeviation="3" />
  <feOffset dx="3" dy="3" />
  <feComponentTransfer>
    <feFuncA type="linear" slope="0.5" />
  </feComponentTransfer>
  <feMerge>
    <feMergeNode />
    <feMergeNode in="SourceGraphic" />
  </feMerge>
</filter>

4. 滤镜串联

代码示例

<filter id="combined">
  <feGaussianBlur in="SourceGraphic" stdDeviation="2" result="blurred" />
  <feColorMatrix in="blurred" type="saturate" values="2" result="saturated" />
  <feOffset in="saturated" dx="2" dy="2" result="offset" />
  <feMerge>
    <feMergeNode in="offset" />
    <feMergeNode in="SourceGraphic" />
  </feMerge>
</filter>

七、代码规范示例

代码示例

<!-- 推荐:滤镜定义规范 -->
<defs>
  <!-- 使用语义化 ID -->
  <filter id="filter-card-shadow" x="-10%" y="-10%" width="120%" height="130%">
    <feDropShadow dx="0" dy="4" stdDeviation="6" flood-color="#000" flood-opacity="0.15" />
  </filter>

  <filter id="filter-glow-blue" x="-30%" y="-30%" width="160%" height="160%">
    <feGaussianBlur in="SourceGraphic" stdDeviation="4" result="blur" />
    <feMerge>
      <feMergeNode in="blur" />
      <feMergeNode in="SourceGraphic" />
    </feMerge>
  </filter>
</defs>

八、常见问题与解决方案

常见问题

滤镜效果被裁剪?

原因是滤镜区域不够大。解决方案是增大 filter 的 x/y/width/height 属性值,确保滤镜效果有足够的空间显示。

feDropShadow 在 Firefox 不工作?

解决方案是使用 feGaussianBlur + feOffset + feFlood + feComposite 组合替代 feDropShadow,这样可以确保跨浏览器兼容性。

滤镜性能差?

解决方案:减少 stdDeviation 值、减少滤镜串联数量、避免在动画元素上使用滤镜。复杂滤镜会显著影响渲染性能。

如何实现发光效果?

使用 feGaussianBlur 模糊原图,然后用 feMerge 将模糊结果和原图合并,即可实现发光效果。需要扩大滤镜区域以避免发光被裁剪。


九、总结

SVG 滤镜是创建高级视觉效果的核心工具,关键要点:

  • filter:定义滤镜,通过 url(#id) 引用

  • feGaussianBlur:高斯模糊,最常用的滤镜

  • feDropShadow:投影阴影(注意兼容性)

  • feColorMatrix:颜色矩阵变换,实现灰度、反色等

  • feTurbulence:噪声纹理

  • feMerge:合并多个滤镜结果

  • 滤镜区域:确保足够大以容纳效果

  • 性能注意:滤镜计算开销大,谨慎使用

下一教程将介绍 SVG 动画。

标签: SVG滤镜 filter标签 高斯模糊 投影阴影 SVG教程 滤镜效果

本文涉及AI创作

内容由AI创作,请仔细甄别

list快速访问

上一篇: 多媒体:SVG图案 - 完整教程与代码示例 下一篇: 多媒体:SVG动画 - 完整教程与代码示例

poll相关推荐