feComposite 滤镜基元用于将两个图像(或者两个滤镜结果)按照一定的规则进行合成。这类似于图像编辑软件(如 Photoshop)中的图层混合模式,但它基于 Porter-Duff 合成操作。
它通常需要两个输入源:
in:背景图in2:前景图它核心属性是 operator,支持以下取值:
over (默认): 前景图覆盖在背景图之上in: 显示前景图与背景图重叠的部位,且显示的是前景图的像素,等同于剪切蒙版效果out: 显示前景图不与背景图重叠的部分,通常用于镂空效果atop: 前景图显示在背景图之上,但只显示背景图存在的区域,但是在重叠区域显示前景图的像素,就像把贴纸贴在物体表面xor: 显示未重叠的区域(异或),重叠区域透明lighter: 简单的加色混合arithmetic: 算术混合,最灵活,通过 k1-k4 系数控制,通过调节 k1-k4 的值,可以实现不同的混合效果1<svg width="0" height="0">2<filter id="my-composite">3<feComposite in="img" in2="SourceGraphic" operator="in" />4</filter>5</svg>
in 操作符显示 输入源 1 位于 输入源 2 内部的区域。这通常用于实现遮罩效果:利用一个形状(in2)来裁剪另一个图像(in)。
此时,in2 是前景图,in 是背景图,当我们使用 operator="in" 时,会显示背景图位于前景图内部的区域。
如下案例,我们将一张风景图限制在文字 "NATURE" 之中。
10<filter id="demo1-composite" x="0" y="0" width="100%" height="100%">20{/* 1. 定义背景图像源 */}30<feImage40href="/images/supercss/81.base/1.png"50x="0" y="0" width="600" height="300"60preserveAspectRatio="xMidYMid slice"70result="img"80/>9010{/*11input1 (in): 背景图12input2 (in2): 前景图:SourceGraphic (即我们的文字)13operator: in => 显示图片,但只在文字区域显示14*/}15<feComposite in="img" in2="SourceGraphic" operator="in" />16{/* 添加阴影效果 */}17<feDropShadow dx="1" dy="1" stdDeviation="0" floodColor="#FFFFFF"/>18</filter>
out 操作符显示 输入源 1 位于 输入源 2 外部的区域。也就是说,相交的部分会被“挖掉”。
这非常适合制作镂空文字效果:在一个实心矩形块中挖出文字形状。
10<filter id="demo2-knockout" x="-10%" y="0" width="120%" height="100%">20{/* 生成一个深色的填充层 */}30<feFlood floodColor="#1f2937" floodOpacity="0.5" result="floodFill" />4050{/*60operator="out"70in="floodFill" (深色层)80in2="SourceAlpha" (文字的轮廓)90结果:显示前景图与背景图不重叠的区域,结果为挖空效果。10*/}11<feComposite in="floodFill" in2="SourceAlpha" operator="out" />12</filter>
atop 操作符会将 输入源 1 绘制在 输入源 2 之上,但仅限于输入源 2 不透明的区域。
这与 in 类似,不同之处在于 atop 会保留输入源 2(背景)的内容,而 in 只保留交集。
这常用于给对象添加纹理或光照,同时保持对象的原始轮廓(alpha 通道)。
如下案例,我们给文字添加了一个金色的纹理。
10<filter id="demo3-atop" x="0" y="0" width="100%" height="100%">20{/* 1. 原始图像 (SourceGraphic) 是下层的银色文字 */}3040{/* 2. 创建上层装饰:一个只占据上半部分的矩形 */}50<feFlood floodColor="#ffd700" result="gold" />60<feOffset in="gold" dy="-60" result="goldMoved" />70{/* 这里用 offset 简单模拟移动,或者直接用 feImage 加 svg rect */}8090{/* 3. 合成:上层装饰 atop 原始文字10效果:装饰层只会显示在文字区域内。11且装饰层透明/未覆盖的地方,会显示原始文字。12*/}13<feComposite14in="topLayer"15in2="SourceGraphic"16operator="atop"17/>18</filter>
xor 操作符显示两个图像不重叠的区域。如果两个不透明像素重叠,则该位置变为全透明。
这可以用于创造有趣的几何图形交互效果。
10<filter id="demo4-xor" x="-50%" y="-50%" width="200%" height="200%">20<feFlood floodColor="#06b6d4" result="color1" />30<feComposite in="color1" in2="SourceGraphic" operator="in" result="shape1" />4050<feOffset in="shape1" dx={-offset.x} dy={-offset.y} result="shifted1" />6070<feFlood floodColor="#ef4444" result="color2" />80<feComposite in="color2" in2="SourceGraphic" operator="in" result="shape2" />9010<feOffset in="shape2" dx={offset.x} dy={offset.y} result="shifted2" />1112{/* XOR 操作:重叠部分透明 */}13<feComposite in="shifted1" in2="shifted2" operator="xor" />14</filter>
arithmetic 是最强大的模式,它通过以下公式计算每个像素的值:
result = k1 * i1 * i2 + k2 * i1 + k3 * i2 + k4
k1: 控制相乘部分(类似正片叠底/相交区域)。k2: 控制输入源 1 的贡献。k3: 控制输入源 2 的贡献。k4: 偏移量(亮度)。通过动态调节 k2 和 k3,我们可以实现两个图像的交叉淡入淡出(Cross Fade) 效果。
10<filter id="demo5-arithmetic" x="0" y="0" width="100%" height="100%">20{/* 1. 源图像 */}30<feImage40href="/images/supercss/81.base/1.png"50x="0" y="0" width="400" height="250"60preserveAspectRatio="xMidYMid slice"70result="img1"80/>9010{/* 2. 第二个源:对原图进行反色处理,模拟另一种风格 */}11<feColorMatrix12in="img1"13type="matrix"14values="-1 0 0 0 1150 -1 0 0 1160 0 -1 0 1170 0 0 1 0"18result="img2"19/>2021{/* 3. 算术混合22公式: result = k1*i1*i2 + k2*i1 + k3*i2 + k423这里我们只用 k2 和 k3 来做线性插值 (Cross Fade)24*/}25<feComposite26in="img1"27in2="img2"28operator="arithmetic"29k1="0"30k2={k2}31k3={k3}32k4="0"33/>34</filter>
我们可以利用 feTurbulence 生成噪点,然后利用 arithmetic 算术运算,将噪点从原始图像中减去,形成斑驳的破损感。
公式:
我们使用 k2 = 1 保留原图,k3 = -1 减去噪点
10<filter id="grunge-text">20{/* 1. 生成粗糙的噪点纹理 */}30<feTurbulence type="fractalNoise" baseFrequency="0.05" numOctaves="3" result="noise" />4050{/* 2. 提高噪点对比度,让黑白分明 */}60<feColorMatrix type="matrix" values="1 0 0 0 0700 1 0 0 0800 0 1 0 0900 0 0 6 -3"10in="noise" result="high-contrast-noise" />1112{/* 3. 算术合成:原图 - 噪点 */}13{/*14k2=1: 100% 原图15k3=-1.5: 减去 1.5倍的噪点亮度 (腐蚀效果)16这会吃掉文字的一部分17*/}18<feComposite operator="arithmetic" k1="0" k2="1" k3="-1.5" k4="0"19in="SourceGraphic" in2="high-contrast-noise" />20</filter>
使用 arithmetic 算术运算,我们可以实现光效合成的效果。
公式:,即
这会让两个重叠的像素亮度相加,产生发光的效果
10<filter id="cyber-glow">20{/* 1. 提取原图 */}30<feImage href="#source-text" result="original"/>4050{/* 2. 偏移并模糊,制造残影 A (青色) */}60<feOffset dx="-5" dy="0" in="SourceGraphic" result="off-a"/>70<feGaussianBlur stdDeviation="4" in="off-a" result="blur-a"/>80<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"/>9010{/* 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"/>1415{/* 4. 混合:青色 + 洋红 (Arithmetic Add) */}16<feComposite operator="arithmetic" k1="0" k2="1" k3="1" k4="0" in="cyan-glow" in2="magenta-glow" result="glow-mix"/>1718{/* 5. 混合:发光背景 + 原图 (White Text) */}19<feComposite operator="arithmetic" k1="0" k2="1" k3="1" k4="0" in="glow-mix" in2="SourceGraphic"/>20</filter>
operator="in"operator="out"operator="atop"operator="over"operator="arithmetic" 算术运算