可复用标签
svg中定义可复用资源需要使用<defs>标签
在<defs>标签中定义可复用资源,然后在需要使用的地方使用<use>标签或者url属性使用,例如
<svg width="400" height="200">
<defs>
<linearGradient id="sky" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#87CEEB" />
<stop offset="100%" stop-color="#ffffff" />
</linearGradient>
</defs>
<rect width="200" height="100" fill="url(#sky)" />
</svg>由此可见,在defs标签中定义可复用资源,并且需要给资源id
然后在需要使用的属性传入url(#id)以使用
复用 defs
<defs> 就是 SVG 的"素材仓库":把东西定义在里面,页面上不会显示,但可以随时被引用复用。
<svg viewBox="0 0 200 100">
<defs>
<!-- 放在这里 = 只定义,不显示 -->
<circle id="dot" cx="10" cy="10" r="10" fill="red" />
<linearGradient id="grad"> ... </linearGradient>
</defs>
<!-- 只有被引用了,才会出现在画布上 -->
<use href="#dot" x="30" y="20" />
<use href="#dot" x="80" y="20" />
</svg><defs> 里通常放什么?
几乎所有"被引用"的东西都应该放在 <defs> 里:
- 渐变:
linearGradient、radialGradient - 可复用图形:
symbol、g - 填充图案:
pattern - 裁剪:
clipPath - 遮罩:
mask - 滤镜:
filter - 箭头标记:
marker - 样式模板:
style
但是上面这些也不是必须要放在defs标签里
symbol:必须linearGradient、radialGradient:必须clipPath:必须filter:放不放都可以,但推荐放里面g:如果只被<use>引用就放里面,如果直接显示就放外面- 基本图形,如rect、circle:如果直接使用就放里面,如果直接显示就放外面
<defs> 的渲染规则
<defs>本身不渲染,被引用后就渲染<defs>的位置不影响引用
注意事项
<defs> 可以嵌套使用,但没必要
<!-- ✅ 完全可以嵌套 -->
<defs>
<g id="outer">
<circle cx="10" cy="10" r="5" />
<defs> <!-- ⚠️ 技术上允许,但没必要 -->
<circle id="inner" cx="20" cy="20" r="3" />
</defs>
</g>
</defs>引用后不能改内部属性
<defs>
<circle id="c" cx="10" cy="10" r="8" fill="red" />
</defs>
<!-- ❌ 这样不会把圆变成蓝色 -->
<use href="#c" fill="blue" />
<!-- ✅ 如果 circle 本身没有设 fill,会继承 use 上的 fill -->
<defs>
<circle id="c2" cx="10" cy="10" r="8" /> <!-- 不写 fill -->
</defs>
<use href="#c2" fill="blue" /> <!-- ✅ 蓝色 -->引用 use
<use>标签用于引用一个元素,
- 不管这个元素是否在
defs标签中,只要这个元素有id,就可以引用 use标签中使用href属性引用一个元素,属性值里id前要加#,比如href="#a"
引用defs内的元素
<svg width="400" height="200">
<defs>
<rect id="r" x="10" y="10" width="50" height="50" />
</defs>
<use href="#r" />
</svg>引用defs外的元素
<svg width="400" height="200">
<rect id="r" x="10" y="10" width="50" height="50" />
<use href="#r" />
</svg>属性
除了上面的href属性,use标签还有以下常用属性
x、y:相对于源元素的位置,等价于transform="translate(x, y)"xlink:href:和href一样,旧版写法,兼容性好但已废弃width/height:尺寸只对<symbol>生效,对<g>、<circle>等无效transform:变换,和 x/y 叠加生效
<svg width="400" height="200">
<rect id="r" x="10" y="10" width="50" height="50" />
<use
href="#r"
x="10"
y="20"
width="40"
height="40"
transform="rotate(15)"
fill="gold"
opacity="0.8" />
</svg>跨 SVG 引用
<use> 最厉害的一点:可以引用页面上任何地方定义的 SVG 元素,甚至跨文件。
<!-- 隐藏的全局图标库 -->
<svg width="0" height="0" style="display:none;">
<defs>
<symbol id="icon-heart" viewBox="0 0 24 24">
<path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5
2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09
C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5
c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/>
</symbol>
</defs>
</svg>
<!-- 页面任何地方都能用 -->
<svg width="24" height="24"><use href="#icon-heart" fill="red"/></svg>
<svg width="48" height="48"><use href="#icon-heart" fill="pink"/></svg>
<svg width="16" height="16"><use href="#icon-heart" fill="crimson"/></svg>分组 g
<g>标签用于将多个标签分成一组,<g>标签上的属性会继承给所有子元素
<svg viewBox="0 0 200 200" width="200" height="200">
<g fill="orange" stroke="black" stroke-width="2">
<circle cx="50" cy="50" r="30" />
<rect x="100" y="20" width="60" height="60" />
<polygon points="50,120 90,180 10,180" />
</g>
</svg>可继承的常用属性
| 类别 | 属性 |
|---|---|
| 填充/描边 | fill、stroke、stroke-width、stroke-dasharray、opacity |
| 变换 | transform |
| 文本 | font-size、font-family、text-anchor |
| 交互 | pointer-events |
| 指针 | cursor |
整体变换
<!-- 整个组旋转 45 度,不用逐个元素算坐标 -->
<g transform="rotate(45 100 100)">
<rect x="70" y="70" width="60" height="60" fill="steelblue" />
<circle cx="100" cy="100" r="15" fill="white" />
</g>加 id + 被 <use> 引用复用
<svg viewBox="0 0 300 150">
<defs>
<!-- 定义一个组 -->
<g id="face">
<circle cx="50" cy="50" r="40" fill="#ffdbac" stroke="#333" stroke-width="2"/>
<circle cx="35" cy="40" r="4" fill="#333"/>
<circle cx="65" cy="40" r="4" fill="#333"/>
<path d="M 35 65 Q 50 80 65 65" stroke="#333" stroke-width="2" fill="none"/>
</g>
</defs>
<!-- 多次复用同一个组 -->
<use href="#face" x="10" y="10" />
<use href="#face" x="120" y="10" />
<use href="#face" x="230" y="10" />
</svg>嵌套编组(层级结构)
<g id="car" transform="translate(0, 0)">
<g id="body" fill="red">
<rect x="10" y="40" width="120" height="30" rx="5" />
</g>
<g id="wheels" fill="#333">
<circle cx="35" cy="75" r="15" />
<circle cx="105" cy="75" r="15" />
</g>
</g>注意事项
1.<use> 的 width/height 能不能缩放 <g>
<!-- ❌ 这样不会缩放 g 里的内容 -->
<use href="#myGroup" width="50" height="50" />
<!-- ✅ 正确做法:在 g 外面包 symbol,或者用 transform -->
<use href="#myGroup" transform="scale(0.5)" />2.<g> 上的 x/y 无效
<!-- ❌ x/y 对 g 不起作用 -->
<g x="50" y="50"> ... </g>
<!-- ✅ 用 transform -->
<g transform="translate(50, 50)"> ... </g>3.<g> 不能直接加文字
<!-- ❌ g 不是文本容器,不能设 x/y 让子文本继承位置 -->
<g x="10" y="10">
<text>Hello</text> <!-- 文字仍然在 (0,0) -->
</g>
<!-- ✅ 文本各自设位置,或统一用 transform -->
<g transform="translate(10, 10)">
<text x="0" y="0">Hello</text>
</g>渐变 gradient
SVG 渐变是一种填充方式,可以替代纯色 fill 或 stroke,让图形呈现从一种颜色到另一种(或多种)颜色的平滑过渡。
SVG 支持两种渐变:
| 类型 | 标签 | 特点 |
|---|---|---|
| 线性渐变 | <linearGradient> | 沿直线方向过渡 |
| 径向渐变 | <radialGradient> | 从圆心向外辐射过渡 |
通过stop标签来控制渐变的锚点,stop标签的属性如下
| 属性 | 默认值 | 说明 |
|---|---|---|
offset | 必填 | 停靠位置(0% ~ 100% 或 0 ~ 1) |
stop-color | black | 该点的颜色 |
stop-opacity | 1 | 该点的透明度 |
渐变不仅可以用于图形的填充fill,也可以用于边框颜色stroke
线性渐变
线性渐变使用linearGradient标签定义,有以下属性
| 属性 | 默认值 | 说明 |
|---|---|---|
x1 | 0% | 渐变起点 X |
y1 | 0% | 渐变起点 Y |
x2 | 100% | 渐变终点 X |
y2 | 0% | 渐变终点 Y |
gradientUnits | objectBoundingBox | 坐标单位系统 |
gradientTransform | 无 | 对渐变做额外变换 |
spreadMethod | pad | 超出区域时如何填充 |
href | 无 | 继承另一个渐变的定义 |
基本使用
<svg viewBox="0 0 300 100" width="300" height="100">
<defs>
<linearGradient id="sky" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#87CEEB" />
<stop offset="100%" stop-color="#ffffff" />
</linearGradient>
</defs>
<rect width="300" height="100" fill="url(#sky)" />
</svg>对角线渐变
<svg viewBox="0 0 300 100" width="300" height="100">
<defs>
<linearGradient id="diag" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="red" />
<stop offset="50%" stop-color="yellow" />
<stop offset="100%" stop-color="blue" />
</linearGradient>
</defs>
<rect width="300" height="100" fill="url(#diag)" />
</svg>多色停靠点
<svg viewBox="0 0 300 100" width="300" height="100">
<defs>
<linearGradient id="rainbow" x1="0%" y2="0%">
<stop offset="0%" stop-color="#f00" />
<stop offset="16.6%" stop-color="#ff0" />
<stop offset="33.3%" stop-color="#0f0" />
<stop offset="50%" stop-color="#0ff" />
<stop offset="66.6%" stop-color="#00f" />
<stop offset="83.3%" stop-color="#f0f" />
<stop offset="100%" stop-color="#f00" />
</linearGradient>
</defs>
<rect width="300" height="100" fill="url(#rainbow)" />
</svg>带透明度的渐变
<svg viewBox="0 0 300 100" width="300" height="100">
<defs>
<linearGradient id="fade" x1="0%" x2="100%">
<stop offset="0%" stop-color="black" stop-opacity="1" />
<stop offset="100%" stop-color="black" stop-opacity="0" />
</linearGradient>
</defs>
<rect width="300" height="100" fill="url(#fade)" />
</svg>径向渐变
线性渐变使用radialGradient标签定义,有以下属性
| 属性 | 默认值 | 说明 |
|---|---|---|
cx | 50% | 渐变中心 X |
cy | 50% | 渐变中心 Y |
r | 50% | 渐变半径 |
fx | 同 cx | 焦点 X(亮斑位置) |
fy | 同 cy | 焦点 Y(亮斑位置) |
fr | 0% | 焦点半径(内圆) |
gradientUnits | objectBoundingBox | 坐标单位系统 |
gradientTransform | 无 | 对渐变做额外变换 |
spreadMethod | pad | 超出区域时如何填充 |
href | 无 | 继承另一个渐变的定义 |
基本使用
<svg viewBox="0 0 200 200" width="200" height="200">
<defs>
<radialGradient id="glow" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="blue" />
<stop offset="100%" stop-color="orange" />
</radialGradient>
</defs>
<circle cx="100" cy="100" r="90" fill="url(#glow)" />
</svg>偏移焦点(制造光照角度)
<svg viewBox="0 0 200 200" width="200" height="200">
<defs>
<radialGradient id="sun" cx="50%" cy="50%" r="50%" fx="35%" fy="35%">
<stop offset="0%" stop-color="skyblue" />
<stop offset="100%" stop-color="gold" />
</radialGradient>
</defs>
<circle cx="100" cy="100" r="90" fill="url(#sun)" />
</svg>内圆 + 外圆(双圆径向渐变)
<svg viewBox="0 0 200 200" width="200" height="200">
<defs>
<radialGradient id="ring" cx="50%" cy="50%" r="50%" fx="50%" fy="50%" fr="20%">
<stop offset="0%" stop-color="transparent" />
<stop offset="100%" stop-color="rgba(0,0,0,0.4)" />
</radialGradient>
</defs>
<circle cx="100" cy="100" r="90" fill="url(#ring)" />
</svg>关键属性
gradientUnits
坐标系统
| 值 | 含义 | 说明 |
|---|---|---|
objectBoundingBox(默认) | 相对于被填充元素的包围盒 | 0~1 或 0%~100%,随元素缩放 |
userSpaceOnUse | 相对于当前用户坐标系 | 用绝对像素值,不随元素缩放 |
spreadMethod
超出区域时的行为
| 值 | 效果 |
|---|---|
pad(默认) | 用最后一个颜色"填充"剩余区域 |
repeat | 渐变重复平铺 |
reflect | 渐变镜像重复(去→回→去→回) |
<svg width="700" height="200">
<defs>
<linearGradient id="pad" x1="0%" x2="20%" spreadMethod="pad">
<stop offset="0%" stop-color="red" />
<stop offset="100%" stop-color="blue" />
</linearGradient>
<linearGradient id="repeat" x1="0%" x2="20%" spreadMethod="repeat">
<stop offset="0%" stop-color="red" />
<stop offset="100%" stop-color="blue" />
</linearGradient>
<linearGradient id="reflect" x1="0%" x2="20%" spreadMethod="reflect">
<stop offset="0%" stop-color="red" />
<stop offset="100%" stop-color="blue" />
</linearGradient>
</defs>
<circle cx="100" cy="100" r="90" fill="url(#pad)" />
<circle cx="300" cy="100" r="90" fill="url(#repeat)" />
<circle cx="500" cy="100" r="90" fill="url(#reflect)" />
</svg>gradientTransform
对渐变做变换,接收和css里transform一样的值
<svg width="700" height="200">
<defs>
<linearGradient id="rotated" x1="0%" y1="0%" x2="100%" y2="0%" gradientTransform="rotate(45)">
<stop offset="0%" stop-color="red" />
<stop offset="100%" stop-color="blue" />
</linearGradient>
</defs>
<circle cx="100" cy="100" r="90" fill="url(#rotated)" />
</svg>href
渐变继承
<svg width="700" height="200">
<defs>
<linearGradient id="base">
<stop offset="0%" stop-color="red" />
<stop offset="100%" stop-color="blue" />
</linearGradient>
<!-- 继承 base,只改方向 -->
<linearGradient id="vertical" href="#base" x1="0%" y1="0%" x2="0%" y2="100%" />
</defs>
<circle cx="100" cy="100" r="50" fill="url(#base)"/>
<circle cx="250" cy="100" r="50" fill="url(#vertical)"/>
</svg>常规操作
渐变作用于描边
<svg viewBox="0 0 300 100">
<defs>
<linearGradient id="strokeGrad" x1="0%" x2="100%">
<stop offset="0%" stop-color="red" />
<stop offset="100%" stop-color="purple" />
</linearGradient>
</defs>
<rect x="20" y="20" width="260" height="60" rx="8" fill="none" stroke="url(#strokeGrad)" stroke-width="8" />
</svg>贴纸 pattern
<pattern> 就是 SVG 的"贴纸模板":定义一小块图案,SVG 会自动把它像瓷砖一样平铺,填满整个形状。
类比 CSS:pattern ≈ background-image + background-repeat,但它是矢量的、可无限缩放的。
<svg>
<defs>
<pattern id="myPattern" width="20" height="20" patternUnits="userSpaceOnUse">
<circle cx="10" cy="10" r="5" fill="red" />
</pattern>
</defs>
<rect fill="url(#myPattern)" x="0" y="0" width="200" height="100" />
</svg>属性
| 属性 | 默认值 | 说明 |
|---|---|---|
x | 0 | 图案起始 X 偏移 |
y | 0 | 图案起始 Y 偏移 |
width | 必填 | 一个图样的宽度(平铺单元宽) |
height | 必填 | 一个图样的高度(平铺单元高) |
patternUnits | objectBoundingBox | 定义 x/y/width/height 的坐标系统 |
patternContentUnits | userSpaceOnUse | 定义内部元素的坐标系统 |
patternTransform | 无 | 对整个图案做变换(旋转/缩放/倾斜) |
viewBox | 无 | 为图案内容定义自己的坐标系 |
preserveAspectRatio | xMidYMid meet | 配合 viewBox 控制缩放对齐 |
href | 无 | 继承另一个 pattern 的定义 |
| id | 无 | 必须,供 url(#id) 引用 |
基本使用
<svg viewBox="0 0 200 120" width="400" height="240">
<defs>
<pattern id="dots" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
<circle cx="10" cy="10" r="3" fill="#2196F3" opacity="0.4" />
</pattern>
</defs>
<rect width="200" height="120" fill="url(#dots)" />
</svg>核心属性
patternUnits
图案尺寸的坐标系统
| 值 | 含义 | 说明 |
|---|---|---|
objectBoundingBox(默认) | 相对于被填充元素的包围盒 | width="0.2" = 元素宽度的 20% |
userSpaceOnUse | 相对于当前用户坐标系 | width="20" = 20px 绝对值 |
<svg width="400" height="240">
<defs>
<!-- 相对模式:图案宽度 = 矩形宽度的 10% -->
<pattern id="p1" width="0.1" height="0.1" patternUnits="objectBoundingBox">
<rect width="100%" height="100%" fill="red" />
</pattern>
<!-- 绝对模式:图案固定 20×20 px,不随矩形大小变化 -->
<pattern id="p2" width="20" height="20" patternUnits="userSpaceOnUse">
<rect width="20" height="20" fill="blue" />
</pattern>
</defs>
<rect x="0" y="0" width="200" height="120" fill="url(#p1)" />
<rect x="200" y="120" width="200" height="120" fill="url(#p2)" />
</svg>
patternContentUnits
内部元素的坐标系统
| 值 | 含义 | 说明 |
|---|---|---|
userSpaceOnUse(默认) | 内部元素用绝对坐标 | cx="10" = 10px |
objectBoundingBox | 内部元素用相对坐标(0~1) | cx="0.5" = 图案宽度的一半 |
<svg width="400" height="240">
<defs>
<!-- 默认:内部用绝对坐标 -->
<pattern id="pp1" width="40" height="40" patternUnits="userSpaceOnUse">
<circle cx="20" cy="20" r="15" />
<!-- 20px 是绝对像素 -->
</pattern>
<!-- 改用相对坐标:圆始终在图案正中心 -->
<pattern
id="pp2"
width="1"
height="1"
patternUnits="objectBoundingBox"
patternContentUnits="objectBoundingBox"
>
<circle cx="0.5" cy="0.5" r="0.4" />
</pattern>
</defs>
<rect x="0" y="0" width="200" height="120" fill="url(#pp1)" />
<rect x="200" y="120" width="200" height="120" fill="url(#pp2)" />
</svg>patternUnits 管"瓷砖多大",patternContentUnits 管"瓷砖上画什么尺寸"。
viewBox
给图案自己的坐标系
<pattern id="checker" width="40" height="40"
patternUnits="userSpaceOnUse"
viewBox="0 0 40 40">
<rect x="0" y="0" width="20" height="20" fill="#ccc" />
<rect x="20" y="20" width="20" height="20" fill="#ccc" />
</pattern>patternTransform
整体变换,接收和css里transform一样的值
<svg width="400" height="240">
<defs>
<pattern
id="striped"
width="10"
height="10"
patternUnits="userSpaceOnUse"
patternTransform="rotate(45)"
>
<rect width="5" height="10" fill="#999" />
</pattern>
</defs>
<rect x="0" y="0" width="200" height="120" fill="url(#striped)" />
</svg>x / y
图案起始偏移,相当于transform:translate(x,y)
<svg width="400" height="240">
<defs>
<pattern id="offset" x="5" y="5" width="20" height="20" patternUnits="userSpaceOnUse">
<circle cx="10" cy="10" r="4" fill="green" />
</pattern>
</defs>
<rect x="0" y="0" width="200" height="120" fill="url(#offset)" />
</svg>href
继承
<svg width="400" height="240">
<defs>
<pattern id="base1" width="20" height="20" patternUnits="userSpaceOnUse">
<circle cx="10" cy="10" r="5" fill="red" />
</pattern>
<!-- 继承 base,只改颜色 -->
<pattern id="blueDots1" href="#base1">
<circle cx="10" cy="10" r="5" fill="blue" />
</pattern>
</defs>
<rect x="0" y="0" width="200" height="120" fill="url(#base1)" />
<rect x="200" y="120" width="200" height="120" fill="url(#blueDots1)" />
</svg>经典案例
棋盘格
<svg width="400" height="240">
<defs>
<pattern id="checker" width="20" height="20" patternUnits="userSpaceOnUse">
<rect x="0" y="0" width="10" height="10" fill="#ddd" />
<rect x="10" y="10" width="10" height="10" fill="#ddd" />
</pattern>
</defs>
<rect x="0" y="0" width="400" height="240" fill="url(#checker)" />
</svg>斜条纹
<svg width="400" height="240">
<defs>
<pattern id="stripes" width="8" height="8" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
<rect x="0" y="0" width="4" height="8" fill="#2196F3" opacity="0.3" />
</pattern>
</defs>
<rect x="0" y="0" width="400" height="240" fill="url(#stripes)" />
</svg>网格线
<svg width="400" height="240">
<defs>
<pattern id="grid" width="20" height="20" patternUnits="userSpaceOnUse">
<path d="M 20 0 L 0 0 0 20" fill="none" stroke="#e0e0e0" stroke-width="1" />
</pattern>
</defs>
<rect x="0" y="0" width="400" height="240" fill="url(#grid)" />
</svg>十字形
<svg width="400" height="240">
<defs>
<pattern id="cross" width="16" height="16" patternUnits="userSpaceOnUse">
<path d="M7 0v16M0 7h16" stroke="#ff5252" stroke-width="2" fill="none" opacity="0.3" />
</pattern>
</defs>
<rect x="0" y="0" width="400" height="240" fill="url(#cross)" />
</svg>文字水印
<svg width="400" height="240">
<defs>
<pattern id="watermark" width="100" height="60" patternUnits="userSpaceOnUse">
<text
x="50"
y="35"
text-anchor="middle"
font-size="14"
fill="#000"
opacity="0.08"
transform="rotate(-30 50 30)"
>
DRAFT
</text>
</pattern>
</defs>
<rect x="0" y="0" width="400" height="240" fill="url(#watermark)" />
</svg>渐变 + pattern 组合
<svg width="400" height="240">
<defs>
<linearGradient id="sky1" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#87CEEB" />
<stop offset="100%" stop-color="#ffffff" />
</linearGradient>
<pattern id="gradDots" width="30" height="30" patternUnits="userSpaceOnUse">
<rect width="30" height="30" fill="url(#sky1)" />
<circle cx="15" cy="15" r="4" fill="white" opacity="0.5" />
</pattern>
</defs>
<rect x="0" y="0" width="400" height="240" fill="url(#gradDots)" />
</svg>滤镜 filter
<filter> 就是 SVG 的"后期特效台":定义一组图像处理操作(模糊、变色、阴影、位移……),SVG 会把它当成一个滤镜链逐条执行,最终输出到画布上。
类比 CSS:
filter属性 ≈ SVG<filter>的简化版。CSSfilter: blur(5px)背后就是调用了一个 SVG 高斯模糊滤镜。但 SVG<filter>能做 CSS 做不到的复杂效果。
filter标签属性
| 属性 | 默认值 | 说明 |
|---|---|---|
id | 必填 | 供 url(#id) 引用 |
x | -10% | 滤镜作用区域 X(可超出元素) |
y | -10% | 滤镜作用区域 Y |
width | 120% | 滤镜作用区域宽 |
height | 120% | 滤镜作用区域高 |
filterUnits | objectBoundingBox | x/y/width/height 的坐标系统 |
primitiveUnits | userSpaceOnUse | 内部原子操作的尺寸单位 |
href | 无 | 继承另一个 filter |
默认滤镜区域是元素的 120%(-10% ~ 110%),做投影时如果阴影被截断,就要手动调大 x/y/width/height。
原子操作标签
这是 SVG 滤镜最强大的部分——每一个 <fe\*> 标签就是一个处理节点,它们串联起来形成"滤镜管线":
| 标签 | 作用 | 类比 |
|---|---|---|
<feGaussianBlur> | 高斯模糊 | filter: blur() |
<feColorMatrix> | 颜色矩阵变换(变灰、反色、调色) | filter: grayscale() contrast() |
<feComponentTransfer> | 逐通道曲线映射 | Photoshop 的 Curves |
<feComposite> | 两图合成(over/in/out/atop/xor) | 图层混合模式 |
<feBlend> | 正片叠底/滤色等混合 | mix-blend-mode |
<feMerge> / <feMergeNode> | 多图层叠加输出 | 图层栈 |
<feOffset> | 位移(做阴影必备) | filter: drop-shadow() 的偏移部分 |
<feDropShadow> | 一步到位做投影 | filter: drop-shadow() |
<feFlood> | 填充纯色/纯色+透明度 | 新建一个纯色图层 |
<feImage> | 引入外部图像参与滤镜 | — |
<feTurbulence> | 生成柏林噪声(云、火焰、大理石纹理) | — |
<feDisplacementMap> | 用一张图扭曲另一张图(水波、玻璃) | 液化工具 |
<feMorphology> | 腐蚀/膨胀(变粗/变细) | — |
<feConvolveMatrix> | 卷积矩阵(锐化、浮雕、边缘检测) | — |
<feDiffuseLighting> | 漫反射光照(3D 凸起感) | — |
<feSpecularLighting> | 高光反射光照(金属光泽) | — |
<feDistantLight> | 远光(配合光照滤镜) | — |
<fePointLight> | 点光源(配合光照滤镜) | — |
<feSpotLight> | 聚光灯(配合光照滤镜) | — |
<feTile> | 平铺一个输入图像 | — |
所有原子标签共享的属性
| 属性 | 说明 |
|---|---|
in | 输入源(见下方说明) |
in2 | 第二输入源(部分标签需要) |
result | 输出命名(供后续标签引用) |
in 的特殊关键字
| 关键字 | 含义 |
|---|---|
SourceGraphic | 原始图形(默认) |
SourceAlpha | 原始图形的 Alpha 通道(黑白遮罩) |
BackgroundImage | 背景图像(很少用) |
BackgroundAlpha | 背景 Alpha |
FillPaint | fill 的内容 |
StrokePaint | stroke 的内容 |
| 自定义名称 | 引用其他原子标签的 result |
feGaussianBlur
高斯模糊
| 属性 | 说明 |
|---|---|
stdDeviation | 模糊半径(越大越糊),可写两个值 x y 做方向性模糊 |
edgeMode | 边缘处理方式(duplicate/wrap/none) |
<svg width="600" height="200">
<defs>
<!-- 基础模糊 -->
<filter id="blur">
<feGaussianBlur stdDeviation="5" />
</filter>
<!-- 水平方向模糊(毛玻璃条效果) -->
<filter id="blurH">
<feGaussianBlur stdDeviation="8 0" />
</filter>
<!-- 单独模糊 Alpha 通道(做柔和阴影用) -->
<filter id="blurAlpha">
<feGaussianBlur in="SourceAlpha" stdDeviation="4" />
</filter>
</defs>
<rect width="200" height="100" fill="skyblue" filter="url(#blur)" />
<rect x="200" y="100" width="200" height="100" fill="skyblue" filter="url(#blurH)" />
<rect x="400" y="0" width="200" height="100" fill="skyblue" filter="url(#blurAlpha)" />
</svg>feDropShadow
步投影
| 属性 | 默认值 | 说明 |
|---|---|---|
dx | 2 | X 偏移 |
dy | 2 | Y 偏移 |
stdDeviation | 2 | 模糊半径 |
flood-color | black | 阴影颜色 |
flood-opacity | 1 | 阴影透明度 |
<svg width="600" height="200">
<defs>
<filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
<feDropShadow dx="3" dy="5" stdDeviation="4" flood-color="#000" flood-opacity="0.3" />
</filter>
</defs>
<rect width="200" height="100" fill="skyblue" filter="url(#shadow)" />
</svg>等价于 CSS
filter: drop-shadow(3px 5px 4px rgba(0,0,0,0.3))。但 SVG 版本可以精确控制区域不截断。
feColorMatrix
颜色矩阵
| 属性 | 说明 |
|---|---|
type | matrix(默认)/ saturate / hueRotate / luminanceToAlpha |
values | 矩阵值或参数 |
type="matrix"
(完整 5×4 矩阵)
R' = r1*R + r2*G + r3*B + r4*A + r5
G' = g1*R + g2*G + g3*B + g4*A + g5
B' = b1*R + b2*G + b3*B + b4*A + b5
A' = a1*R + a2*G + a3*B + a4*A + a5<svg width="600" height="200" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="gray">
<feColorMatrix
type="matrix"
values="0.33 0.33 0.33 0 0
0.33 0.33 0.33 0 0
0.33 0.33 0.33 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>
<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>
</defs>
<image href="https://picsum.photos/200/100" x="0" y="0" width="200" height="100" filter="url(#gray)" />
<image href="https://picsum.photos/200/100" x="200" y="100" width="200" height="100" filter="url(#invert)" />
<image href="https://picsum.photos/200/100" x="400" y="0" width="200" height="100" filter="url(#sepia)" />
</svg>type="saturate"
饱和度
<svg width="600" height="200" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="saturate_zero">
<feColorMatrix type="saturate" values="0" />
</filter>
<filter id="saturate_Tow">
<feColorMatrix type="saturate" values="2" />
</filter>
<filter id="saturate_five">
<feColorMatrix type="saturate" values="5" />
</filter>
</defs>
<image href="https://picsum.photos/200/100" x="0" y="0" width="200" height="100" filter="url(#saturate_zero)" />
<image
href="https://picsum.photos/200/100"
x="200"
y="100"
width="200"
height="100"
filter="url(#saturate_Tow)"
/>
<image
href="https://picsum.photos/200/100"
x="400"
y="0"
width="200"
height="100"
filter="url(#saturate_five)"
/>
</svg>type="hueRotate"
色相旋转,度数
<svg width="600" height="200" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="saturate_zero">
<feColorMatrix type="hueRotate" values="45" />
</filter>
<filter id="saturate_Tow">
<feColorMatrix type="hueRotate" values="90" />
</filter>
<filter id="saturate_five">
<feColorMatrix type="hueRotate" values="150" />
</filter>
</defs>
<image
href="https://picsum.photos/200/100"
x="0"
y="0"
width="200"
height="100"
filter="url(#saturate_zero)"
/>
<image
href="https://picsum.photos/200/100"
x="200"
y="100"
width="200"
height="100"
filter="url(#saturate_Tow)"
/>
<image
href="https://picsum.photos/200/100"
x="400"
y="0"
width="200"
height="100"
filter="url(#saturate_five)"
/>
</svg>type="luminanceToAlpha"
亮度转透明度
<svg width="200" height="100" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="saturate_zero">
<feColorMatrix type="luminanceToAlpha" />
</filter>
</defs>
<image
href="https://picsum.photos/200/100"
x="0"
y="0"
width="200"
height="100"
filter="url(#saturate_zero)"
/>
</svg>feOffset
位移
<svg width="600" height="200" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="shift">
<feOffset dx="10" dy="10" />
</filter>
</defs>
<rect x="0" y="0" width="200" height="100" filter="url(#shift)" />
<rect x="0" y="0" width="200" height="100"/>
</svg>
feMerge / feMergeNode
多图层叠加
<svg width="500" height="300" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="layered">
<feGaussianBlur in="SourceAlpha" stdDeviation="6" result="GLOW" />
<feOffset in="SourceGraphic" dx="20" dy="0" result="SHIFT" />
<feMerge>
<feMergeNode in="GLOW" />
<feMergeNode in="SHIFT" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<image
href="https://picsum.photos/400/200"
x="0"
y="0"
width="400"
height="200"
filter="url(#layered)"
/>
</svg>顺序:后写的 <feMergeNode> 在上层(类似 CSS z-index 反过来理解)。
feTurbulence
柏林噪声(纹理生成器)
| 属性 | 说明 |
|---|---|
type | fractalNoise(云/烟雾)或 turbulence(火焰/大理石) |
baseFrequency | 噪声频率(越小越平滑,越大越细碎) |
numOctaves | 叠加层数(越大越有细节,性能越差) |
seed | 随机种子(改它换一种纹理) |
<svg width="600" height="400" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- 云朵纹理 -->
<filter id="clouds">
<feTurbulence type="fractalNoise" baseFrequency="0.01" numOctaves="4" />
</filter>
<!-- 大理石纹理 -->
<filter id="marble">
<feTurbulence type="turbulence" baseFrequency="0.02" numOctaves="3" />
</filter>
</defs>
<rect width="200" height="100" filter="url(#clouds)" />
<rect x="200" y="100" width="200" height="100" filter="url(#marble)" />
</svg>通常配合 <feDisplacementMap> 或 <feColorMatrix> 使用,把噪声"染色"。
feDisplacementMap
图像扭曲
| 属性 | 说明 |
|---|---|
in | 被扭曲的图像 |
in2 | 扭曲用的地图(通常是 turbulence 的输出) |
scale | 扭曲强度 |
xChannelSelector | 用哪个通道控制 X 方向(R/G/B/A) |
yChannelSelector | 用哪个通道控制 Y 方向 |
<svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- 水波效果 -->
<filter id="water">
<feTurbulence type="fractalNoise" baseFrequency="0.02" numOctaves="2" result="NOISE" />
<feDisplacementMap in="SourceGraphic" in2="NOISE" scale="15" />
</filter>
</defs>
<rect width="200" height="100" filter="url(#water)" fill="skyblue"/>
</svg>feComposite
| 属性 | 说明 |
|---|---|
operator | over(默认)/ in / out / atop / xor / arithmetic |
<svg width="600" height="400" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- 只在图形内部显示图案(类似 clipPath) -->
<filter id="mask">
<feImage href="https://picsum.photos/400/200" result="PATTERN" />
<feComposite in="PATTERN" in2="SourceAlpha" operator="in" />
</filter>
</defs>
<rect width="200" height="100" filter="url(#mask)" />
</svg>feBlend
混合模式
| 属性 | 说明 |
|---|---|
mode | normal / multiply / screen / overlay / darken / lighten / color-dodge / color-burn / hard-light / soft-light / difference / exclusion / hue / saturation / color / luminosity |
<svg width="600" height="400" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="multiply">
<feFlood flood-color="yellow" result="YELLOW" />
<feBlend in="SourceGraphic" in2="YELLOW" mode="multiply" />
</filter>
</defs>
<rect width="200" height="100" filter="url(#multiply)" />
</svg>综合示例
<svg viewBox="0 0 600 400" width="600" height="400" style="border:1px solid #ddd;">
<defs>
<!-- 1. 柔和投影 -->
<filter id="softShadow" x="-20%" y="-20%" width="140%" height="140%">
<feDropShadow dx="0" dy="8" stdDeviation="12" flood-color="#000" flood-opacity="0.25" />
</filter>
<!-- 2. 霓虹发光 -->
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceGraphic" stdDeviation="8" result="BLUR" />
<feMerge>
<feMergeNode in="BLUR" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
<!-- 3. 毛玻璃 -->
<filter id="glass">
<feGaussianBlur in="SourceGraphic" stdDeviation="10" />
</filter>
<!-- 4. 灰度 + 对比度 -->
<filter id="dramatic">
<feColorMatrix type="matrix"
values="1.2 0 0 0 -0.1
0 1.2 0 0 -0.1
0 0 1.2 0 -0.1
0 0 0 1 0" />
</filter>
<!-- 5. 水波扭曲 -->
<filter id="ripple" x="-20%" y="-20%" width="140%" height="140%">
<feTurbulence type="fractalNoise" baseFrequency="0.03" numOctaves="2" result="NOISE" />
<feDisplacementMap in="SourceGraphic" in2="NOISE" scale="10" />
</filter>
</defs>
<!-- 展示 -->
<rect x="20" y="20" width="160" height="100" rx="12" fill="#4CAF50" filter="url(#softShadow)" />
<text x="100" y="72" text-anchor="middle" fill="white" font-size="14">投影</text>
<circle cx="310" cy="70" r="45" fill="#E91E63" filter="url(#glow)" />
<text x="310" y="155" text-anchor="middle" fill="#666" font-size="14">发光</text>
<rect x="420" y="20" width="160" height="100" rx="12" fill="url(#grad)" filter="url(#glass)" />
<text x="500" y="72" text-anchor="middle" fill="#333" font-size="14">毛玻璃</text>
<image href="photo.jpg" x="20" y="180" width="160" height="100" filter="url(#dramatic)" />
<text x="100" y="300" text-anchor="middle" fill="#666" font-size="14">高对比</text>
<text x="310" y="240" font-size="72" font-weight="bold" fill="#2196F3"
filter="url(#ripple)">WAVE</text>
<text x="310" y="340" text-anchor="middle" fill="#666" font-size="14">水波</text>
<rect x="420" y="180" width="160" height="100" rx="8" fill="#FF9800" filter="url(#softShadow)" />
<text x="500" y="300" text-anchor="middle" fill="white" font-size="14">组合效果</text>
</svg>
