登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  前端

SVG feDisplacementMap 怎样选择位移使用的颜色通道

来源:17golang原创

时间:2026-10-31 03:10:20 104浏览 收藏

我第一次把 SVG 的波纹贴图接到 上时,最容易改错的不是 scale,而是颜色通道:明明换了一张位移图,画面却只沿一个方向抖动,或者透明区域突然把文字拉成一条线。实际选择规则很直接:xChannelSelector 决定水平方向读取哪个通道,yChannelSelector 决定垂直方向读取哪个通道;通道可以是 R、G、B 或 A,默认值是 A。

要点速览
  • 先问位移图把数据放在哪个通道,再填写选择器;不要按“红色更适合横向”这类固定经验硬套。
  • 同一张灰度图可以让 x、y 都读取同一个通道;RGB 彩色位移图则可以把两组数据拆到不同通道。
  • scale 控制位移幅度,通道值 0.5 是中性点,低于和高于 0.5 的值分别产生相反方向的偏移。

先把颜色通道当成位移数据源

feDisplacementMap 使用 in2 的像素值来移动 in 的像素。选择器的职责不是给画面“上色”,而是告诉滤镜:每个输出像素的水平坐标和垂直坐标分别从哪一个通道取数。

我现在会先在纸上写一行数据约定:R 存水平位移、G 存垂直位移,或者两个方向都从灰度通道读取。约定确定以后,属性就不会跟着视觉效果反复试错。

SVG feDisplacementMap 的颜色通道与水平垂直位移轴关系说明图
图1:feDisplacementMap 的颜色通道与位移轴关系说明图,不是运行截图。

R、G、B、A 应该怎样选

四个通道在语义上没有“谁更高级”的排序,真正的选择取决于 in2 的数据布局。下表是我在设计位移贴图时使用的速查表:

通道它表示什么适合的情况容易踩的坑
R红色分量把一组独立的水平或垂直数据放进 RGB 贴图误以为画面越红,位移一定越大;实际还要看数值和 scale
G绿色分量与 R 配对存放第二组方向数据图像软件的颜色预览可能掩盖了通道真实数值
B蓝色分量需要第三组数据,或已有蓝色通道位移图蓝色视觉较明显不等于通道数值更适合
A透明度分量用透明度作为遮罩或已有带 alpha 的灰度位移图默认值就是 A,透明区域可能被误当成零位移

如果位移图是普通灰度图,通常最省心的写法是让 xChannelSelector 和 yChannelSelector 都指向实际存放灰度值的通道,并显式写出来。这样即使后来替换了素材,也不必猜浏览器默认取的是哪一层。

灰度图不要把默认 A 当成约定

很多 PNG 的可见灰度内容都在 RGB 里,但它可能没有有意义的 alpha。此时若省略选择器,默认的 A 通道可能整张都是 1,结果就是位移图看起来有纹理,滤镜却没有按纹理改变方向。

下面的示例把红色通道用于横向、绿色通道用于纵向。两通道都以 0.5 附近作为中性值,便于把一张彩色位移图拆成两个方向:


    WAVE
  

这里的 feTurbulence 只是生成示例用的 in2,不是位移算法本身。换成真实图片时,仍然要确认图片是否真的把两组方向数据放进了 R、G;如果只是一张透明度遮罩,应改成 A/A 或把灰度数据转换到明确的通道。

scale 决定位移幅度,0.5 是中性点

scale 不是“强度开关”,而是把通道值相对于 0.5 的偏离放大。通道值接近 0.5 时,位移接近零;低于 0.5 与高于 0.5 会产生相反方向。把 scale 调大只会放大已有方向,不会改变你选择的通道。

SVG feDisplacementMap 的 scale 与 0.5 中性值关系示意图
图2:通道值、0.5 中性点与 scale 的位移关系示意图,不是运行截图。

因此我通常按这个顺序调参:

  1. 先把 scale 设为较小的正数,确认画面确实在变化。
  2. 固定 scale,单独替换 xChannelSelector,观察水平变化是否来自预期通道。
  3. 再替换 yChannelSelector,确认垂直变化没有被同一通道或 alpha 覆盖。
  4. 最后才扩大 scale,并给滤镜留出足够的边界区域,避免内容被裁掉。

同一通道和两个通道,分别适合什么场景

只做柔和的水波、玻璃或噪声扰动时,同一张灰度图同时给 x、y 使用很实用,素材简单,调试成本低。想做有明确方向的风吹、斜切或地形起伏时,R/G 分开存两组值会更好控制。A 通道则适合“透明度就是位移权重”的素材,但必须确认 alpha 是有意设计的,而不是导出图片时顺手留下的透明层。

一个小经验是:如果切换通道后画面完全不动,不要立刻把 scale 调到很大。先检查通道是否接近常量、是否被预乘 alpha 影响,以及素材的可见纹理是否真的对应了该通道的数值。

用最小检查清单确认选择没有错

  • 检查输入:in2 是否确实指向位移图或上一个滤镜结果。
  • 检查选择器:明确写出 xChannelSelector 和 yChannelSelector,不要依赖默认 A。
  • 检查数据:选中的通道是否有变化,是否把整张图导出成了常量或全透明。
  • 检查幅度:先用小 scale,再逐步增加,避免把裁剪问题误认为通道错误。
  • 检查方向:交换 R/G 或交换 x/y 选择器,若变化方向随之交换,说明映射关系生效。
const displacement = document.querySelector('#ripple');

// 只改变通道选择器,保留 scale,便于隔离方向问题。
function swapChannels() {
  const x = displacement.querySelector('feDisplacementMap');
  const oldX = x.getAttribute('xChannelSelector') || 'A';
  const oldY = x.getAttribute('yChannelSelector') || 'A';
  x.setAttribute('xChannelSelector', oldY);
  x.setAttribute('yChannelSelector', oldX);
}

// 调试完成后仍保留显式属性,避免素材或默认值变化带来回归。
swapChannels();

最后的选择原则

选择颜色通道时,先看位移图的数据契约,再看视觉效果:水平数据放在哪里,垂直数据放在哪里,就分别把 x、y 选择器指向哪里。灰度图可以复用同一通道,彩色图可以拆分 R/G/B,alpha 图则使用 A。把选择器写明、把 0.5 当成中性点、把 scale 留到最后调,通常比盲目换颜色更快定位问题。

常见问题

省略 xChannelSelector 和 yChannelSelector 会默认读取什么?

默认值是 A。如果你的位移图没有有意义的 alpha,最好显式指定实际存放位移数据的通道。

能让 x 和 y 都使用 R 通道吗?

可以。对于单通道灰度位移图,这是常见写法;它表示两个方向共享同一份位移数据,而不是 R 天生代表水平方向。

为什么把 scale 调大后画面只是被裁掉?

位移幅度变大后,内容可能超出滤镜区域。先确认通道和方向,再扩大滤镜的 x、y、width、height,不要用更大的 scale 掩盖边界设置问题。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>