Skip to content

SVG 阴影效果

所有 SVG 滤镜效果都在 <defs> 元素内定义。<defs> (定义) 元素是可重用图形对象的容器,这些对象不直接渲染,但可以被其他元素引用。

<filter> 元素定义了一个 SVG 滤镜。它需要一个 id 属性,为滤镜提供一个唯一的名称。然后图形可以使用 filter 属性应用此滤镜(例如,filter=“url(#filterId)”)。一个滤镜可以包含一个或多个滤镜原语(filter primitives),这些原语执行特定的图形操作。

<filter> 元素上的 x、y、width 和 height 属性定义了滤镜效果区域。通常需要使此区域大于目标元素,以容纳模糊或偏移等超出元素原始边界的效果。

<feOffset> 滤镜原语用于通过偏移输入图形来创建诸如阴影之类的效果。

<feOffset> 原语接受一个输入图形(由 in 属性指定,对于原始元素通常是 SourceGraphic),并按指定的量沿 x(dx)和 y(dy)方向移动它。此操作的结果(由 result 属性指定)可以被其他滤镜原语使用。在这个例子中,我们偏移了一个矩形,然后使用 <feBlend> 将原始图形与其偏移版本组合。

从视觉上看,这会创建一个简单的、边缘锐利的阴影,其中原始的黄色矩形在其下方有一个略微偏移的相同副本。

以下是 SVG 代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>SVG feOffset Example 1</title>
</head>
<body>
<svg width="150" height="150">
<defs>
<filter id="f1" x="-20%" y="-20%" width="140%" height="140%">
<feOffset in="SourceGraphic" dx="10" dy="10" result="offOut" />
<feBlend in="SourceGraphic" in2="offOut" mode="normal" />
</filter>
</defs>
<rect width="90" height="90" x="10" y="10" stroke="green" stroke-width="3" fill="yellow" filter="url(#f1)" />
</svg>
</body>
</html>

代码解释 (示例 1):

  • <filter id=“f1” …>: 定义 ID 为 “f1” 的滤镜并扩展滤镜区域。
  • <feOffset in=“SourceGraphic” dx=“10” dy=“10” result=“offOut” />: 获取原始图形(SourceGraphic),向下移动 10 个单位,向右移动 10 个单位,并将输出命名为 offOut。
  • <feBlend in=“SourceGraphic” in2=“offOut” mode=“normal” />: 获取原始图形(SourceGraphic)和偏移图形(offOut)并将它们混合。mode=“normal” 通常意味着顶层(如果 SourceGraphic 排在前面,或按照混合输入的默认分层)绘制在底层之上。
  • filter=“url(#f1)”: 将滤镜 “f1” 应用于矩形。

示例 2: 添加模糊以获得更柔和的阴影

Section titled “示例 2: 添加模糊以获得更柔和的阴影”

为了创建更逼真、更柔和的阴影,我们可以在混合之前使用 <feGaussianBlur> 滤镜原语模糊偏移图像。

从视觉上看,这会给偏移副本添加模糊,使阴影看起来更柔和、更分散,这对于逼真的阴影来说是典型的。

以下是 SVG 代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>SVG feOffset Example 2</title>
</head>
<body>
<svg width="180" height="180">
<defs>
<filter id="f2" x="-40%" y="-40%" width="180%" height="180%">
<feOffset in="SourceGraphic" dx="10" dy="10" result="offOut" />
<feGaussianBlur in="offOut" stdDeviation="5" result="blurOut" />
<feMerge>
<feMergeNode in="blurOut" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<rect width="90" height="90" x="20" y="20" stroke="green" stroke-width="3" fill="yellow" filter="url(#f2)" />
</svg>
</body>
</html>

代码解释 (示例 2):

  • <feGaussianBlur in=“offOut” stdDeviation=“5” result=“blurOut” />: 获取 feOffset 的结果(offOut)并应用标准差为 5 的高斯模糊。stdDeviation 值越高,结果越模糊。输出命名为 blurOut。
  • <feMerge>: 此原语用于组合多个图层。<feMergeNode> 指定每个图层。在这里,模糊的阴影(blurOut)先绘制,然后在其顶部绘制原始图形(SourceGraphic)。这是一种在滤镜中对元素进行分层的常用方法,是 feBlend 的替代方案,用于简单的堆叠。

示例 3: 使用 SourceAlpha 创建黑色阴影

Section titled “示例 3: 使用 SourceAlpha 创建黑色阴影”

通常,您希望阴影是特定颜色(如黑色或灰色),而不是原始图形颜色的偏移副本。为此,您可以使用 SourceAlpha 作为 feOffset 的输入。SourceAlpha 表示原始图形的 alpha 通道(透明度信息)。然后我们使用 <feFlood> 创建纯色,并使用 <feComposite> 将其与 alpha 蒙版组合。

从视觉上看,通过使用 ‘SourceAlpha’,阴影变成形状的纯黑色(或由 feFlood 定义的颜色)轮廓,经过模糊和偏移,而不是原始图形的有色偏移。

以下是 SVG 代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>SVG feOffset Example 3</title>
</head>
<body>
<svg width="180" height="180">
<defs>
<filter id="f3" x="-40%" y="-40%" width="180%" height="180%">
<!-- Create a black flood fill -->
<feFlood flood-color="black" flood-opacity="0.7" result="flood" />
<!-- Use SourceAlpha and composite with flood to colorize the shadow shape -->
<feComposite in="flood" in2="SourceAlpha" operator="in" result="shadowBase"/>
<!-- Offset the shadow shape -->
<feOffset in="shadowBase" dx="10" dy="10" result="offOut" />
<!-- Blur the offset shadow -->
<feGaussianBlur in="offOut" stdDeviation="5" result="blurOut" />
<!-- Merge the shadow and the original graphic -->
<feMerge>
<feMergeNode in="blurOut" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<rect width="90" height="90" x="20" y="20" stroke="green" stroke-width="3" fill="yellow" filter="url(#f3)" />
</svg>
</body>
</html>

代码解释 (示例 3):

  • <feFlood flood-color=“black” flood-opacity=“0.7” result=“flood” />: 创建一个无限平面的纯色(黑色,70% 不透明度)。
  • <feComposite in=“flood” in2=“SourceAlpha” operator=“in” result=“shadowBase”/>: 获取填充颜色和源图形的 alpha 通道。operator=“in” 表示输出是 flood 颜色,但仅限于与 SourceAlpha 重叠的部分(有效地为源图形的形状着色)。
  • 滤镜链的其余部分(feOffset、feGaussianBlur、feMerge)然后处理此 shadowBase。

<feColorMatrix> 滤镜原语允许通过对输入的 RGBA 通道应用矩阵变换来进行更复杂的颜色操作。

这可用于去饱和、着色或以其他方式改变阴影的颜色。

从视觉上看,颜色矩阵滤镜允许对阴影的颜色进行精细控制。在这种情况下,它为阴影创建了原始图形颜色的去饱和、更暗版本。

以下是 SVG 代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>SVG feOffset Example 4</title>
</head>
<body>
<svg width="180" height="180">
<defs>
<filter id="f4" x="-40%" y="-40%" width="180%" height="180%">
<feOffset in="SourceGraphic" dx="10" dy="10" result="offOut" />
<feColorMatrix in="offOut" type="matrix"
values="0.2 0 0 0 0
0 0.2 0 0 0
0 0 0.2 0 0
0 0 0 1 0" result="matrixOut" />
<feGaussianBlur in="matrixOut" stdDeviation="5" result="blurOut" />
<feMerge>
<feMergeNode in="blurOut" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<rect width="90" height="90" x="20" y="20" stroke="green" stroke-width="3" fill="yellow" filter="url(#f4)" />
</svg>
</body>
</html>

代码解释 (示例 4):

  • <feColorMatrix … values=”…” />: 此滤镜将偏移图形(offOut)作为输入。values 属性定义了一个用于 RGBA 变换的 5x4 矩阵。此处提供的矩阵(0.2 0 0 0 0 / 0 0.2 0 0 0 / 0 0 0.2 0 0 / 0 0 0 1 0)有效地将 R、G 和 B 通道按其原始值的 20% 进行缩放,使阴影更暗、去饱和,同时保持 alpha 通道(A)不变。

学习提示: SVG 滤镜功能强大,但也可能很复杂。从简单的原语(如 feOffset 和 feGaussianBlur)开始,然后逐步探索更高级的原语。像 SVG Filter Builder 这样的工具可以帮助可视化和构建滤镜效果。