Table of Contents

1概述

feComposite 滤镜基元用于将两个图像(或者两个滤镜结果)按照一定的规则进行合成。这类似于图像编辑软件(如 Photoshop)中的图层混合模式,但它基于 Porter-Duff 合成操作。

它通常需要两个输入源:

  • in:背景图
  • in2:前景图

它核心属性是 operator,支持以下取值:

  • over (默认): 前景图覆盖在背景图之上
  • in: 显示前景图与背景图重叠的部位,且显示的是前景图的像素,等同于剪切蒙版效果
  • out: 显示前景图不与背景图重叠的部分,通常用于镂空效果
  • atop: 前景图显示在背景图之上,但只显示背景图存在的区域,但是在重叠区域显示前景图的像素,就像把贴纸贴在物体表面
  • xor: 显示未重叠的区域(异或),重叠区域透明
  • lighter: 简单的加色混合
  • arithmetic: 算术混合,最灵活,通过 k1-k4 系数控制,通过调节 k1-k4 的值,可以实现不同的混合效果
index.html
1
<svg width="0" height="0">
2
<filter id="my-composite">
3
<feComposite in="img" in2="SourceGraphic" operator="in" />
4
</filter>
5
</svg>

2Operator: in (遮罩/裁剪)

in 操作符显示 输入源 1 位于 输入源 2 内部的区域。这通常用于实现遮罩效果:利用一个形状(in2)来裁剪另一个图像(in)。

此时,in2 是前景图,in 是背景图,当我们使用 operator="in" 时,会显示背景图位于前景图内部的区域。

如下案例,我们将一张风景图限制在文字 "NATURE" 之中。

预览
index.tsx
1
<filter id="demo1-composite" x="0" y="0" width="100%" height="100%">
2
{/* 1. 定义背景图像源 */}
3
<feImage
4
href="/images/supercss/81.base/1.png"
5
x="0" y="0" width="600" height="300"
6
preserveAspectRatio="xMidYMid slice"
7
result="img"
8
/>
9
10
{/*
11
input1 (in): 背景图
12
input2 (in2): 前景图:SourceGraphic (即我们的文字)
13
operator: in => 显示图片,但只在文字区域显示
14
*/}
15
<feComposite in="img" in2="SourceGraphic" operator="in" />
16
{/* 添加阴影效果 */}
17
<feDropShadow dx="1" dy="1" stdDeviation="0" floodColor="#FFFFFF"/>
18
</filter>

3Operator: out (挖空/镂空)

out 操作符显示 输入源 1 位于 输入源 2 外部的区域。也就是说,相交的部分会被“挖掉”。

这非常适合制作镂空文字效果:在一个实心矩形块中挖出文字形状。

预览
index.tsx
1
<filter id="demo2-knockout" x="-10%" y="0" width="120%" height="100%">
2
{/* 生成一个深色的填充层 */}
3
<feFlood floodColor="#1f2937" floodOpacity="0.5" result="floodFill" />
4
5
{/*
6
operator="out"
7
in="floodFill" (深色层)
8
in2="SourceAlpha" (文字的轮廓)
9
结果:显示前景图与背景图不重叠的区域,结果为挖空效果。
10
*/}
11
<feComposite in="floodFill" in2="SourceAlpha" operator="out" />
12
</filter>

4Operator: atop (纹理叠加)

atop 操作符会将 输入源 1 绘制在 输入源 2 之上,但仅限于输入源 2 不透明的区域

这与 in 类似,不同之处在于 atop 会保留输入源 2(背景)的内容,而 in 只保留交集。 这常用于给对象添加纹理或光照,同时保持对象的原始轮廓(alpha 通道)。

如下案例,我们给文字添加了一个金色的纹理。

预览
index.tsx
1
<filter id="demo3-atop" x="0" y="0" width="100%" height="100%">
2
{/* 1. 原始图像 (SourceGraphic) 是下层的银色文字 */}
3
4
{/* 2. 创建上层装饰:一个只占据上半部分的矩形 */}
5
<feFlood floodColor="#ffd700" result="gold" />
6
<feOffset in="gold" dy="-60" result="goldMoved" />
7
{/* 这里用 offset 简单模拟移动,或者直接用 feImage 加 svg rect */}
8
9
{/* 3. 合成:上层装饰 atop 原始文字
10
效果:装饰层只会显示在文字区域内。
11
且装饰层透明/未覆盖的地方,会显示原始文字。
12
*/}
13
<feComposite
14
in="topLayer"
15
in2="SourceGraphic"
16
operator="atop"
17
/>
18
</filter>

5Operator: xor (排除/异或)

xor 操作符显示两个图像不重叠的区域。如果两个不透明像素重叠,则该位置变为全透明。

这可以用于创造有趣的几何图形交互效果。

预览
index.tsx
1
<filter id="demo4-xor" x="-50%" y="-50%" width="200%" height="200%">
2
<feFlood floodColor="#06b6d4" result="color1" />
3
<feComposite in="color1" in2="SourceGraphic" operator="in" result="shape1" />
4
5
<feOffset in="shape1" dx={-offset.x} dy={-offset.y} result="shifted1" />
6
7
<feFlood floodColor="#ef4444" result="color2" />
8
<feComposite in="color2" in2="SourceGraphic" operator="in" result="shape2" />
9
10
<feOffset in="shape2" dx={offset.x} dy={offset.y} result="shifted2" />
11
12
{/* XOR 操作:重叠部分透明 */}
13
<feComposite in="shifted1" in2="shifted2" operator="xor" />
14
</filter>

6Operator: arithmetic (算术混合)

arithmetic 是最强大的模式,它通过以下公式计算每个像素的值: result = k1 * i1 * i2 + k2 * i1 + k3 * i2 + k4

  • k1: 控制相乘部分(类似正片叠底/相交区域)。
  • k2: 控制输入源 1 的贡献。
  • k3: 控制输入源 2 的贡献。
  • k4: 偏移量(亮度)。

通过动态调节 k2k3,我们可以实现两个图像的交叉淡入淡出(Cross Fade) 效果。

预览
index.tsx
1
<filter id="demo5-arithmetic" x="0" y="0" width="100%" height="100%">
2
{/* 1. 源图像 */}
3
<feImage
4
href="/images/supercss/81.base/1.png"
5
x="0" y="0" width="400" height="250"
6
preserveAspectRatio="xMidYMid slice"
7
result="img1"
8
/>
9
10
{/* 2. 第二个源:对原图进行反色处理,模拟另一种风格 */}
11
<feColorMatrix
12
in="img1"
13
type="matrix"
14
values="-1 0 0 0 1
15
0 -1 0 0 1
16
0 0 -1 0 1
17
0 0 0 1 0"
18
result="img2"
19
/>
20
21
{/* 3. 算术混合
22
公式: result = k1*i1*i2 + k2*i1 + k3*i2 + k4
23
这里我们只用 k2 和 k3 来做线性插值 (Cross Fade)
24
*/}
25
<feComposite
26
in="img1"
27
in2="img2"
28
operator="arithmetic"
29
k1="0"
30
k2={k2}
31
k3={k3}
32
k4="0"
33
/>
34
</filter>

7实践:做旧/腐蚀纹理

我们可以利用 feTurbulence 生成噪点,然后利用 arithmetic 算术运算,将噪点从原始图像中减去,形成斑驳的破损感。

公式:Result=k1i1i2+k2i1+k3i2+k4Result = k1 * i1 * i2 + k2 * i1 + k3 * i2 + k4

我们使用 k2 = 1 保留原图,k3 = -1 减去噪点

预览
index.tsx
1
<filter id="grunge-text">
2
{/* 1. 生成粗糙的噪点纹理 */}
3
<feTurbulence type="fractalNoise" baseFrequency="0.05" numOctaves="3" result="noise" />
4
5
{/* 2. 提高噪点对比度,让黑白分明 */}
6
<feColorMatrix type="matrix" values="1 0 0 0 0
7
0 1 0 0 0
8
0 0 1 0 0
9
0 0 0 6 -3"
10
in="noise" result="high-contrast-noise" />
11
12
{/* 3. 算术合成:原图 - 噪点 */}
13
{/*
14
k2=1: 100% 原图
15
k3=-1.5: 减去 1.5倍的噪点亮度 (腐蚀效果)
16
这会吃掉文字的一部分
17
*/}
18
<feComposite operator="arithmetic" k1="0" k2="1" k3="-1.5" k4="0"
19
in="SourceGraphic" in2="high-contrast-noise" />
20
</filter>

8实践:光效合成

使用 arithmetic 算术运算,我们可以实现光效合成的效果。

公式:Result=i1+i2Result = i1 + i2,即 k2=1,k3=1k2 = 1, k3 = 1

这会让两个重叠的像素亮度相加,产生发光的效果

预览
index.tsx
1
<filter id="cyber-glow">
2
{/* 1. 提取原图 */}
3
<feImage href="#source-text" result="original"/>
4
5
{/* 2. 偏移并模糊,制造残影 A (青色) */}
6
<feOffset dx="-5" dy="0" in="SourceGraphic" result="off-a"/>
7
<feGaussianBlur stdDeviation="4" in="off-a" result="blur-a"/>
8
<feColorMatrix in="blur-a" type="matrix" values="0 0 0 0 0 0 1 0 0 0 0 0 1 0 1 0 0 0 1 0" result="cyan-glow"/>
9
10
{/* 3. 偏移并模糊,制造残影 B (洋红) */}
11
<feOffset dx="5" dy="0" in="SourceGraphic" result="off-b"/>
12
<feGaussianBlur stdDeviation="4" in="off-b" result="blur-b"/>
13
<feColorMatrix in="blur-b" type="matrix" values="1 0 0 0 1 0 0 0 0 0 0 0 1 0 1 0 0 0 1 0" result="magenta-glow"/>
14
15
{/* 4. 混合:青色 + 洋红 (Arithmetic Add) */}
16
<feComposite operator="arithmetic" k1="0" k2="1" k3="1" k4="0" in="cyan-glow" in2="magenta-glow" result="glow-mix"/>
17
18
{/* 5. 混合:发光背景 + 原图 (White Text) */}
19
<feComposite operator="arithmetic" k1="0" k2="1" k3="1" k4="0" in="glow-mix" in2="SourceGraphic"/>
20
</filter>

9总结

  • 简单的遮罩,把图片放进文字里:用 operator="in"
  • 复杂的挖空、内阴影、镂空:用 operator="out"
  • 贴图、纹理、在物体表面加材质:用 operator="atop"
  • 外描边、背景垫底:配合膨胀滤镜用 operator="over"
  • 光效、做旧、滤色:用 operator="arithmetic" 算术运算
专栏首页
到顶
专栏目录