feDisplacementMap 是 SVG 滤镜中最强大的滤镜之一. 也是最具破坏性的滤镜之一.
他和 PS 中的置换滤镜的原理是一样的, 都是通过一个图像的颜色值来改变另一个图像的像素位置.
他可以利用一张图(通常是纹路或者噪声)的颜色信息, 来推挤另外一张图的像素, 从而产生扭曲、液化、变形、故障、手绘等风格.
他的参数如下:
in: 要被变形的原始图像.in2: 置换图(Displacement Map), 通常是噪点或特定的梯度图.scale: 变形的强度. 值越大, 拉伸/扭曲越严重.xChannelSelector / yChannelSelector: 指定用置换图的哪个颜色通道(R, G, B, A)来控制 X 轴或 Y 轴的偏移. 通常设置:R 控制 X, G 控制 Y滤镜会遍历 in 的每一个像素, 查看 in2 对应位置的颜色值
feTurbulence 可以在不基于任何图像的情况下, 生成噪点纹理. 从云彩、大理石、水波, 到如今设计圈大火的“噪点渐变”和“磨砂质感”, 核心全是它. 本文中的案例, 也会大量借助他来实现.
他的关键参数如下
baseFrequency: 控制噪点的频率. 值越大, 噪点越密集.
numOctaves: 控制噪点的层数, 即细节丰富度
type: 类型, 有两种:
turbulence: 湍流噪点, 产生随机、不规则的噪点, 适合火焰、爆炸等效果fractalNoise: 分形噪点, 产生更自然的条纹, 适合云雾、柔和过渡的场景最常见的用法是结合 feTurbulence 生成的噪点来实现水波纹效果.
我们让噪点在 baseFrequency 上进行动画, 从而带动置换效果的流动.
01<filter id="demo1-ripple">02{/* 1. 生成大尺度的湍流噪点, 模拟水波 */}03<feTurbulence04type="turbulence"05baseFrequency="0.01 0.015" // X方向高频 (0.01) => 密集的噪点, Y方向低频 (0.015) => 拉伸的长条06numOctaves="2"07result="noise"08>09{/* 让噪点动起来 */}10<animate attributeName="baseFrequency" values="0.01 0.015;0.01 0.025;0.01 0.015" dur="10s" repeatCount="indefinite" />11</feTurbulence>1213{/* 2. 使用噪点置换原图 */}14<feDisplacementMap15in="SourceGraphic"16in2="noise"17scale="20"18xChannelSelector="R" // 使用红色通道控制X偏移19yChannelSelector="G" // 使用绿色通道控制Y偏移20/>21</filter>
通过控制噪点的频率(X 轴高频, Y 轴低频), 我们可以制造出水平方向的撕裂效果, 非常适合赛博朋克风格的故障文字.
01<filter id="demo2-glitch">02<feTurbulence03type="fractalNoise" // 使用分形噪点, 产生更自然的条纹04baseFrequency="0.5 0.005" // X方向高频 (0.5) => 密集的噪点, Y方向低频 (0.005) => 拉伸的长条05numOctaves="2" // 噪点层数, 层数越多, 条纹越明显06result="noise"07/>0809<feDisplacementMap10in="SourceGraphic"11in2="noise"12scale="20"13xChannelSelector="R"14yChannelSelector="G"15/>16</filter>
利用高频噪点进行细微的像素置换, 可以模拟磨砂玻璃的粗糙表面. 这实际上是一种高级的模糊, 比 feGaussianBlur 更有质感.
01<filter id="demo3-frost">02<feTurbulence03type="fractalNoise" // 使用分形噪点, 产生更自然的条纹04baseFrequency={baseFrequency} // 高频噪点, 产生细小的颗粒感05numOctaves="3" // 噪点层数, 层数越多, 颗粒感越强06stitchTiles="stitch"07result="noise"08/>09<feDisplacementMap10in="SourceGraphic"11in2="noise"12scale="10"13xChannelSelector="R"14yChannelSelector="G"15/>16</filter>
给规则的几何图形或文字添加低频噪点的置换, 可以让线条变得不规则, 模仿手绘的颤抖线条效果.
01<filter id="demo4-sketch">02<feTurbulence03type="fractalNoise" // 使用分形噪点, 产生更自然的条纹04baseFrequency="0.04" // 低频噪点, 产生规则的条纹05numOctaves="3" // 噪点层数, 层数越多, 条纹越明显06result="noise"07/>08<feDisplacementMap09in="SourceGraphic"10in2="noise"11scale="5"12xChannelSelector="R"13yChannelSelector="G"14/>15</filter>
结合 React 的状态管理, 我们可以动态改变 scale 属性.
鼠标悬停时瞬间增大 scale, 可以制作出“受到干扰”或“全息投影不稳定”的酷炫交互效果.
01'use client'02import { useState } from 'react'0304export default function App() {05const [scale, setScale] = useState(0)0607return (08<div09className="w-full h-full flex flex-col items-center justify-center bg-gray-900 rounded-xl p-8 relative overflow-hidden"10onMouseEnter={() => setScale(30)}11onMouseLeave={() => setScale(0)}12>13<svg className='w-full max-w-[400px] cursor-pointer' viewBox="0 0 400 250">14<defs>15<filter id="demo5-interact">16<feTurbulence17type="fractalNoise" // 使用分形噪点, 产生更自然的条纹18baseFrequency="0.1 0.01" // X方向高频 (0.1) => 密集的噪点, Y方向低频 (0.01) => 拉伸的长条19numOctaves="2" // 噪点层数, 层数越多, 条纹越明显20result="noise"21>22<animate attributeName="baseFrequency" values="0.1 0.01; 0.1 0.04; 0.1 0.01" dur="0.2s" repeatCount="indefinite" />23</feTurbulence>2425<feDisplacementMap26in="SourceGraphic"27in2="noise"28scale={scale} // 变形的强度. 值越大, 拉伸/扭曲越严重.29xChannelSelector="R" // 使用红色通道控制X偏移30yChannelSelector="G" // 使用绿色通道控制Y偏移31className="transition-all duration-300"32/>33</filter>34</defs>3536<g filter="url(#demo5-interact)">37<rect x="20" y="20" width="360" height="210" rx="15" fill="#6366f1" />38<text x="50" y="80" fontFamily="sans-serif" fontSize="24" fill="white" fontWeight="bold">HOVER CARD</text>39</g>40</svg>41</div>42)43}
通过控制噪点的频率(X 轴高频, Y 轴低频), 我们可以制造出水平方向的撕裂效果, 非常适合赛博朋克风格的故障文字.
1<filter id="melt-filter">2{/* 定义两个维度的噪声, Y轴频率稍低, 模拟重力下垂感 */}3<feTurbulence type="turbulence" baseFrequency="0.02 0.08" numOctaves="3" seed="5" result="noise">4{/* SVG 动画让流体动起来 */}5<animate attributeName="baseFrequency" dur="10s" values="0.02 0.08;0.02 0.1;0.02 0.08" repeatCount="indefinite"/>6</feTurbulence>7{/* 使用噪点置换原图 */}8<feDisplacementMap in="SourceGraphic" in2="noise" scale="30" xChannelSelector="R" yChannelSelector="G" />9</filter>
feDisplacementMap 的核心在于 in2 (置换图) 的设计:
1<filter id="ripple-filter">2{/* 低频噪声, 模拟缓和的水波 */}3<feTurbulence type="turbulence" baseFrequency="0.02 0.02" numOctaves="2" seed="2" result="ripple">4<animate attributeName="baseFrequency" dur="5s" values="0.01 0.01;0.02 0.04;0.01 0.01" repeatCount="indefinite" />5</feTurbulence>6{/* 稍微增加一点 scale */}7<feDisplacementMap in="SourceGraphic" in2="ripple" scale="20" xChannelSelector="R" yChannelSelector="G" />8</filter>