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 动画