Skip to content

SVG 渐变与滤镜

SVG 提供了强大的渐变和滤镜系统。渐变用于创建平滑的颜色过渡效果,滤镜用于实现模糊、阴影、颜色矩阵变换等视觉效果。通过 <defs> 定义渐变和滤镜,然后在图形元素中引用,可以创造出丰富的视觉表现。本节将详细介绍 SVG 渐变与滤镜的使用方法。

前置知识

阅读本节前,建议先了解:SVG 路径

基础概念

SVG 渐变和滤镜都定义在 <defs> 元素中,通过 id 属性进行引用。<defs> 中的内容不会直接渲染,而是作为可复用的资源。

defs 的作用

html
<svg width="400" height="300" viewBox="0 0 400 300">
  <!-- 定义区域:内容不会直接渲染 -->
  <defs>
    <linearGradient id="myGrad">
      <stop offset="0%" stop-color="#4285f4"/>
      <stop offset="100%" stop-color="#ea4335"/>
    </linearGradient>
    <filter id="myBlur">
      <feGaussianBlur stdDeviation="3"/>
    </filter>
  </defs>

  <!-- 引用定义 -->
  <rect x="50" y="50" width="200" height="100" fill="url(#myGrad)"/>
  <text x="100" y="200" font-size="24" filter="url(#myBlur)">模糊文字</text>
</svg>

渐变

线性渐变 linearGradient

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>SVG 渐变</title>
  <style>
    svg { border: 1px solid #ccc; display: block; margin: 10px 0; }
  </style>
</head>
<body>
  <h1>SVG 渐变</h1>

  <svg width="500" height="300" viewBox="0 0 500 300">
    <defs>
      <!-- 水平线性渐变(默认方向) -->
      <linearGradient id="gradH" x1="0%" y1="0%" x2="100%" y2="0%">
        <stop offset="0%" stop-color="#4285f4"/>
        <stop offset="100%" stop-color="#34a853"/>
      </linearGradient>

      <!-- 垂直线性渐变 -->
      <linearGradient id="gradV" x1="0%" y1="0%" x2="0%" y2="100%">
        <stop offset="0%" stop-color="#ea4335"/>
        <stop offset="50%" stop-color="#fbbc05"/>
        <stop offset="100%" stop-color="#34a853"/>
      </linearGradient>

      <!-- 对角线渐变 -->
      <linearGradient id="gradD" x1="0%" y1="0%" x2="100%" y2="100%">
        <stop offset="0%" stop-color="#9c27b0"/>
        <stop offset="100%" stop-color="#4285f4"/>
      </linearGradient>
    </defs>

    <!-- 水平渐变矩形 -->
    <rect x="20" y="20" width="140" height="80" rx="8" fill="url(#gradH)"/>
    <text x="60" y="75" font-size="11" fill="white" text-anchor="middle">水平渐变</text>

    <!-- 垂直渐变矩形 -->
    <rect x="180" y="20" width="140" height="80" rx="8" fill="url(#gradV)"/>
    <text x="250" y="75" font-size="11" fill="white" text-anchor="middle">垂直渐变</text>

    <!-- 对角渐变矩形 -->
    <rect x="340" y="20" width="140" height="80" rx="8" fill="url(#gradD)"/>
    <text x="410" y="75" font-size="11" fill="white" text-anchor="middle">对角渐变</text>

    <!-- 带多个停止点的渐变 -->
    <defs>
      <linearGradient id="gradMulti">
        <stop offset="0%" stop-color="#ea4335"/>
        <stop offset="25%" stop-color="#fbbc05"/>
        <stop offset="50%" stop-color="#34a853"/>
        <stop offset="75%" stop-color="#4285f4"/>
        <stop offset="100%" stop-color="#9c27b0"/>
      </linearGradient>
    </defs>

    <rect x="20" y="130" width="460" height="40" rx="8" fill="url(#gradMulti)"/>
    <text x="250" y="155" font-size="12" fill="white" text-anchor="middle">多色渐变(彩虹)</text>
  </svg>
</body>
</html>

linearGradient 属性

属性说明默认值
id唯一标识符必填
x1, y1渐变起点(百分比或 0~1)0%
x2, y2渐变终点100%
gradientUnits坐标系objectBoundingBox
gradientTransform变换矩阵
spreadMethod填充方式pad

径向渐变 radialGradient

html
<svg width="400" height="200" viewBox="0 0 400 200">
  <defs>
    <!-- 基本径向渐变 -->
    <radialGradient id="radial1" cx="50%" cy="50%" r="50%">
      <stop offset="0%" stop-color="#ffffff"/>
      <stop offset="50%" stop-color="#4285f4"/>
      <stop offset="100%" stop-color="#1a237e"/>
    </radialGradient>

    <!-- 偏心径向渐变 -->
    <radialGradient id="radial2" cx="30%" cy="30%" r="50%">
      <stop offset="0%" stop-color="#ff5722"/>
      <stop offset="100%" stop-color="#4285f4"/>
    </radialGradient>
  </defs>

  <circle cx="100" cy="100" r="80" fill="url(#radial1)"/>
  <circle cx="300" cy="100" r="80" fill="url(#radial2)"/>
</svg>

radialGradient 属性

属性说明默认值
cx, cy渐变中心50%
r渐变半径50%
fx, fy焦点位置cx, cy 相同

stop 元素

html
<stop offset="0%" stop-color="#4285f4" stop-opacity="1"/>
属性说明
offset停止点位置(0%~100%
stop-color颜色值
stop-opacity透明度(0~1

滤镜

feGaussianBlur - 高斯模糊

html
<svg width="400" height="150" viewBox="0 0 400 150">
  <defs>
    <filter id="blur1">
      <feGaussianBlur stdDeviation="1"/>
    </filter>
    <filter id="blur5">
      <feGaussianBlur stdDeviation="5"/>
    </filter>
  </defs>

  <text x="20" y="40" font-size="24" fill="#333">无模糊</text>
  <text x="20" y="80" font-size="24" fill="#333" filter="url(#blur1)">轻微模糊</text>
  <text x="20" y="120" font-size="24" fill="#333" filter="url(#blur5)">强烈模糊</text>
</svg>

feDropShadow - 投影

html
<svg width="400" height="200" viewBox="0 0 400 200">
  <defs>
    <filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
      <feDropShadow dx="4" dy="4" stdDeviation="3" flood-color="rgba(0,0,0,0.3)"/>
    </filter>
  </defs>

  <rect x="50" y="30" width="150" height="100" rx="10"
        fill="#4285f4" filter="url(#shadow)"/>
  <text x="125" y="90" font-size="16" fill="white" text-anchor="middle">带阴影</text>
</svg>

feColorMatrix - 颜色矩阵

html
<svg width="400" height="200" viewBox="0 0 400 200">
  <defs>
    <!-- 灰度效果 -->
    <filter id="grayscale">
      <feColorMatrix type="matrix"
        values="0.299 0.587 0.114 0 0
                0.299 0.587 0.114 0 0
                0.299 0.587 0.114 0 0
                0     0     0     1 0"/>
    </filter>

    <!-- 棕褐色 -->
    <filter id="sepia">
      <feColorMatrix type="matrix"
        values="0.393 0.769 0.189 0 0
                0.349 0.686 0.168 0 0
                0.272 0.534 0.131 0 0
                0     0     0     1 0"/>
    </filter>

    <!-- 反色 -->
    <filter id="invert">
      <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>

  <!-- 原始 -->
  <circle cx="70" cy="100" r="50" fill="#4285f4"/>
  <text x="70" y="170" font-size="12" text-anchor="middle">原始</text>

  <!-- 灰度 -->
  <circle cx="200" cy="100" r="50" fill="#4285f4" filter="url(#grayscale)"/>
  <text x="200" y="170" font-size="12" text-anchor="middle">灰度</text>

  <!-- 反色 -->
  <circle cx="330" cy="100" r="50" fill="#4285f4" filter="url(#invert)"/>
  <text x="330" y="170" font-size="12" text-anchor="middle">反色</text>
</svg>

滤镜链(组合多个滤镜)

html
<svg width="400" height="200" viewBox="0 0 400 200">
  <defs>
    <!-- 模糊 + 阴影 -->
    <filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
      <!-- 模糊层 -->
      <feGaussianBlur in="SourceGraphic" stdDeviation="8" result="blur"/>
      <!-- 颜色偏移 -->
      <feColorMatrix in="blur" type="matrix"
        values="1 0 0 0 0.2
                 0 1 0 0 0
                 0 0 1 0 0.2
                 0 0 0 1 0" result="glow"/>
      <!-- 合并原图和发光层 -->
      <feMerge>
        <feMergeNode in="glow"/>
        <feMergeNode in="SourceGraphic"/>
      </feMerge>
    </filter>
  </defs>

  <text x="200" y="100" font-size="40" fill="#4285f4" text-anchor="middle"
        font-weight="bold" filter="url(#glow)">发光文字</text>
</svg>

常用滤镜原语

原语说明关键属性
feGaussianBlur高斯模糊stdDeviation
feDropShadow投影dx, dy, stdDeviation, flood-color
feColorMatrix颜色矩阵变换type, values
feMerge合并多个图层feMergeNode
feOffset偏移dx, dy
feComposite图层合成operator, in, in2
feTurbulence噪点生成baseFrequency, numOctaves, type
feDisplacementMap位移映射scale, in, in2

实战示例

示例:渐变与滤镜综合

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>渐变与滤镜综合</title>
  <style>
    svg { border: 1px solid #ccc; display: block; margin: 10px 0; }
  </style>
</head>
<body>
  <h1>SVG 渐变与滤镜综合</h1>

  <svg width="500" height="400" viewBox="0 0 500 400">
    <defs>
      <!-- 渐变定义 -->
      <linearGradient id="bgGrad" x1="0%" y1="0%" x2="100%" y2="100%">
        <stop offset="0%" stop-color="#1a237e"/>
        <stop offset="100%" stop-color="#4285f4"/>
      </linearGradient>

      <radialGradient id="glowGrad" cx="50%" cy="50%" r="50%">
        <stop offset="0%" stop-color="#ffffff" stop-opacity="0.8"/>
        <stop offset="100%" stop-color="#4285f4" stop-opacity="0"/>
      </radialGradient>

      <!-- 滤镜定义 -->
      <filter id="cardShadow" x="-10%" y="-10%" width="120%" height="130%">
        <feDropShadow dx="0" dy="4" stdDeviation="8" flood-color="rgba(0,0,0,0.3)"/>
      </filter>

      <filter id="textGlow" x="-20%" y="-20%" width="140%" height="140%">
        <feGaussianBlur in="SourceGraphic" stdDeviation="4" result="blur"/>
        <feMerge>
          <feMergeNode in="blur"/>
          <feMergeNode in="SourceGraphic"/>
        </feMerge>
      </filter>

      <filter id="noise">
        <feTurbulence type="fractalNoise" baseFrequency="0.65" numOctaves="3" stitchTiles="stitch"/>
        <feColorMatrix type="saturate" values="0"/>
      </filter>
    </defs>

    <!-- 背景卡片 -->
    <rect x="20" y="20" width="460" height="360" rx="16"
          fill="url(#bgGrad)" filter="url(#cardShadow)"/>

    <!-- 装饰光球 -->
    <circle cx="250" cy="150" r="80" fill="url(#glowGrad)"/>

    <!-- 标题文字 -->
    <text x="250" y="80" font-size="28" fill="white" text-anchor="middle"
          font-weight="bold" filter="url(#textGlow)">SVG 渐变与滤镜</text>

    <!-- 内容 -->
    <text x="250" y="260" font-size="14" fill="rgba(255,255,255,0.8)"
          text-anchor="middle">使用渐变创建丰富的颜色过渡效果</text>
    <text x="250" y="285" font-size="14" fill="rgba(255,255,255,0.8)"
          text-anchor="middle">使用滤镜添加模糊、阴影等视觉效果</text>

    <!-- 底部装饰条 -->
    <rect x="20" y="350" width="460" height="30" rx="0 0 16 16"
          fill="url(#bgGrad)" opacity="0.5"/>
    <text x="250" y="370" font-size="11" fill="rgba(255,255,255,0.6)"
          text-anchor="middle">defs 中定义,url() 中引用</text>
  </svg>
</body>
</html>

注意事项

1. 滤镜区域

默认情况下,滤镜效果可能被裁剪。使用 x, y, width, height 属性扩大滤镜区域:

html
<!-- 默认滤镜区域可能不够大 -->
<filter id="shadow">
  <!-- 扩大区域以容纳阴影 -->
  <filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
    <feDropShadow dx="5" dy="5" stdDeviation="5"/>
  </filter>
</filter>

2. 渐变坐标系统

html
<!-- objectBoundingBox(默认):相对于目标元素 -->
<linearGradient id="grad1" x1="0" y1="0" x2="1" y2="0">
  <stop offset="0%" stop-color="red"/>
  <stop offset="100%" stop-color="blue"/>
</linearGradient>

<!-- userSpaceOnUse:使用 SVG 坐标系 -->
<linearGradient id="grad2" x1="0" y1="0" x2="400" y2="0"
                gradientUnits="userSpaceOnUse">
  <stop offset="0%" stop-color="red"/>
  <stop offset="100%" stop-color="blue"/>
</linearGradient>

3. 性能影响

滤镜(尤其是模糊和噪声)在复杂 SVG 上可能影响性能:

滤镜性能影响建议
feDropShadow常用,性能可接受
feGaussianBlur避免大 stdDeviation
feColorMatrix性能较好
feTurbulence避免在动画中使用

最佳实践

1. 复用渐变和滤镜

html
<defs>
  <!-- 一个渐变,多处使用 -->
  <linearGradient id="primaryGrad">
    <stop offset="0%" stop-color="#4285f4"/>
    <stop offset="100%" stop-color="#34a853"/>
  </linearGradient>
</defs>

<rect fill="url(#primaryGrad)"/>
<circle fill="url(#primaryGrad)"/>
<path fill="url(#primaryGrad)"/>

2. 命名规范

html
<defs>
  <!-- 渐变用 grad 前缀 -->
  <linearGradient id="gradPrimary"/>
  <linearGradient id="gradHeaderBg"/>
  <radialGradient id="gradAvatarGlow"/>

  <!-- 滤镜用 filter 前缀 -->
  <filter id="filterShadow"/>
  <filter id="filterBlur"/>
  <filter id="filterTextGlow"/>
</defs>

下一节

继续学习:SVG 动画

参考链接