SVG滤镜feColorMatrix总结

起因

最近写了很多关于SVG滤镜的内容,但大部分都是直接呈现了一个效果,并没有去详细的记录关于各个滤镜的详细用法,这次想换个写作风格也是给自己留个备忘录~

往期SVG滤镜相关内容

feColorMatrix

<feColorMatrix> 是 SVG 滤镜中的一个元素,用于对图形的颜色值进行转换和调整。它通过 5x4 的矩阵操作,对每个像素的红色 (R)、绿色 (G)、蓝色 (B) 和透明度 (A) 进行重新计算,从而实现各种颜色效果,如色调旋转、灰度化、饱和度调整等。

python 复制代码
| R' |     | r1 r2 r3 r4 r5 |   | R |
| G' |     | g1 g2 g3 g4 g5 |   | G |
| B' |  =  | b1 b2 b3 b4 b5 | * | B |
| A' |     | a1 a2 a3 a4 a5 |   | A |

计算公式可以展开为:

  • R' = r1 * R + r2 * G + r3 * B + r4 * A + r5
  • G' = g1 * R + g2 * G + g3 * B + g4 * A + g5
  • B' = b1 * R + b2 * G + b3 * B + b4 * A + b5
  • A' = a1 * R + a2 * G + a3 * B + a4 * A + a5

矩阵中的值决定了颜色的最终效果。

属性说明

  1. type 属性

    定义矩阵的类型,常见值包括:

    • matrix:手动指定矩阵值。
    • saturate:调整饱和度。
    • hueRotate:旋转色相。
    • luminanceToAlpha:将亮度值转换为透明度值。
  2. values 属性

    当 type="matrix" 时,用于指定 5x4 的矩阵值。值用空格或逗号分隔。

saturate

saturate变换会影响图像中每个像素的颜色强度(从灰度到全彩)。feColorMatrixsaturate 功能通过指定 values 属性来设定饱和度的值。

  • values="1" 表示图像保持原样,即饱和度没有变化。
  • values="0" 会将图像变成完全灰度(无饱和度,所有颜色都转为灰色)。
  • values > 1 会增加图像的饱和度,使颜色更加鲜艳。
  • values < 0 会反向饱和(通常结果类似于反转色彩)。

可以拖拽saturate查看效果

hueRotate

色相旋转通过改变颜色在色轮上的位置来调整颜色。例如红色可能会变成蓝色或绿色蓝色可能会变成绿色或红色

  • values="0" 表示不旋转,图像保持原样。
  • values="90" 将色相旋转 90°。
  • values="180" 将色相旋转 180°,通常会反转颜色。
  • values="360" 等价于不旋转(颜色循环一圈回到原点)。

可以拖拽hueRotate查看效果

luminanceToAlpha

feColorMatrix 中的 luminanceToAlpha 是一个特殊的类型,它将图像的亮度信息(即每个像素的光亮程度)转换为透明度信息(Alpha 通道)

这个属性可谓是最难理解的属性之一了,光看定义完全无法理解,还是看个例子先!

luminanceToAlpha不接受value,也不受R、G、B影响只受亮度影响,其中亮度(Luminance)的算法是
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> L u m i n a n c e = 0.2126 × R + 0.7152 × G + 0.0722 × B Luminance=0.2126×R+0.7152×G+0.0722×B </math>Luminance=0.2126×R+0.7152×G+0.0722×B

  • 亮度较高的区域会被映射的更接近不透明也可以理解成黑色
  • 亮度较低的区域会映射为较低的 Alpha 值,即更加透明。

luminanceToAlpha常常会配合其他滤镜一起使用,这里先不过多的展开🤖,知道这个属性的功能效果先~

matrix

matrix是整个feColorMatrix中最重要的属性,上述介绍的其他属性都可以通过matrix来实现!

<feColorMatrix> 中的 type="matrix" 是一种通过矩阵操作来修改图像颜色和透明度的方式。这种方法可以直接对图像的颜色通道进行数学运算,改变每个像素的颜色值。与其他类型的 feColorMatrix(如 saturate 或 hueRotate)相比,matrix 提供了更大的灵活性,允许开发者自定义颜色转换的具体方式。

matrix 采用的是一个 4x5 的矩阵结构,矩阵的每一行与颜色的 R、G、B 和 A 分量相对应,最后一列是一个额外的偏移值,具体的公式如下
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> R ′ = ( R × m 11 ) + ( G × m 12 ) + ( B × m 13 ) + ( A × m 14 ) + m 15 G ′ = ( R × m 21 ) + ( G × m 22 ) + ( B × m 23 ) + ( A × m 24 ) + m 25 B ′ = ( R × m 31 ) + ( G × m 32 ) + ( B × m 33 ) + ( A × m 34 ) + m 35 A ′ = ( R × m 41 ) + ( G × m 42 ) + ( B × m 43 ) + ( A × m 44 ) + m 45 R' = (R \times m_{11}) + (G \times m_{12}) + (B \times m_{13}) + (A \times m_{14}) + m_{15} \\ G' = (R \times m_{21}) + (G \times m_{22}) + (B \times m_{23}) + (A \times m_{24}) + m_{25} \\ B' = (R \times m_{31}) + (G \times m_{32}) + (B \times m_{33}) + (A \times m_{34}) + m_{35} \\ A' = (R \times m_{41}) + (G \times m_{42}) + (B \times m_{43}) + (A \times m_{44}) + m_{45} </math>R′=(R×m11)+(G×m12)+(B×m13)+(A×m14)+m15G′=(R×m21)+(G×m22)+(B×m23)+(A×m24)+m25B′=(R×m31)+(G×m32)+(B×m33)+(A×m34)+m35A′=(R×m41)+(G×m42)+(B×m43)+(A×m44)+m45

这里,m_{ij} 代表矩阵中的元素,而 R, G, B, A 是图像的每个像素的颜色通道值,并且矩阵中的输入颜色值是归一化到 0~1 的浮点数范围内,而不是直接使用 0~255 的整数范围。这种归一化的方式适用于所有输入的 RGB 和 Alpha 通道值。

举一个例子!

html 复制代码
.box {
        width: 400px;
        height: 400px;
        background: rgba(255, 0, 0, 1);
        filter: url(#matrix);
}

...
...

<svg>
    <filter id="matrix">
        <feColorMatrix type="matrix" values="
                1 0 0 0 0
                0 1 0 0 0
                0 0 1 0 0
                0 0 0 1 0"/>
    </filter>
</svg>

带入到公式中
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> 1 = ( 1 × 1 ) + ( 0 × 0 ) + ( 0 × 0 ) + ( 1 × 0 ) + 0 0 = ( 1 × 0 ) + ( 0 × 1 ) + ( 0 × 0 ) + ( 1 × 0 ) + 0 0 = ( 1 × 0 ) + ( 0 × 0 ) + ( 0 × 1 ) + ( 1 × 0 ) + 0 1 = ( 1 × 0 ) + ( 0 × 0 ) + ( 0 × 0 ) + ( 1 × 1 ) + 0 1 = (1 \times 1) + (0 \times 0) + (0 \times 0) + (1 \times 0) + 0 \\ 0 = (1 \times 0) + (0 \times 1) + (0 \times 0) + (1 \times 0) + 0 \\ 0 = (1 \times 0) + (0 \times 0) + (0 \times 1) + (1 \times 0) + 0 \\ 1 = (1 \times 0) + (0 \times 0) + (0 \times 0) + (1 \times 1) + 0 \\ </math>1=(1×1)+(0×0)+(0×0)+(1×0)+00=(1×0)+(0×1)+(0×0)+(1×0)+00=(1×0)+(0×0)+(0×1)+(1×0)+01=(1×0)+(0×0)+(0×0)+(1×1)+0

最终输出结果会重新映射到 0 ~ 255 的整数范围
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> R = 1 = 255 , G = 0 = 0 , B = 0 = 0 , A = 1 = 255 R = 1 = 255, \quad G = 0 = 0, \quad B = 0 = 0, \quad A = 1 = 255 </math>R=1=255,G=0=0,B=0=0,A=1=255

这个矩阵保证了所有颜色通道依然保持原有的色值,所以上述例子中的红色矩形最终依然保持了红色!

如果我们想让红色的矩形变成绿色,只需要让红色通道最终结果为0,绿色通道最终结果为1

html 复制代码
 <feColorMatrix type="matrix" values="
                0 0 0 0 0  👈红色通道最后结果全部为0
                0 1 0 0 1  👈绿色通道最终偏移加上1也就是255
                0 0 1 0 0
                0 0 0 1 0"/>

效果展示

利用matrix我们可以完成很多有意思的效果

灰度展示

ini 复制代码
 <feColorMatrix type="matrix" values="
               0.2126 0.7152 0.0722 0 0
               0.2126 0.7152 0.0722 0 0
               0.2126 0.7152 0.0722 0 0
               0      0      0      1 0"/>

灰度看腻了?我们把红色通道的权重修改一下再看看效果~

这也突显了matrix的自由,可以任意配置数值改变原图~

去色(黑白)

html 复制代码
values="
  0.33 0.33 0.33 0 0
  0.33 0.33 0.33 0 0
  0.33 0.33 0.33 0 0
  0    0    0    1 0"

降低亮度

html 复制代码
values="
  1 0 0 0 -0.2
  0 1 0 0 -0.2
  0 0 1 0 -0.2
  0 0 0 1 0"

色相转换

html 复制代码
values="
  0  1  0  0 0
  0  0  1  0 0
  1  0  0  0 0
  0  0  0  1 0"

将原来的 RGB 值重新排列:R → G,G → B,B → R,形成色相旋转。

粘滞效果

这个技巧在H5 实现超丝滑ChatGPT语音交互中有使用到过

html 复制代码
<svg width="400" height="400">
   
    <defs>
        <filter id="goo">
            <feGaussianBlur stdDeviation="15"></feGaussianBlur>
            <feColorMatrix type="matrix" values="
                                         1 0 0 0 0
                                         0 1 0 0 0
                                         0 0 1 0 0
                                         0 0 0 26 -7">
            </feColorMatrix>
        </filter>
    </defs>

    <g filter="url(#goo)">
        <circle cx="200" cy="200" r="20" fill="white"></circle>
        <circle cx="300" cy="200" r="20" fill="white">
            <animate
                    attributeName="cx"
                    from="300"
                    to="100"
                    dur="4s"
                    repeatCount="indefinite"/>
        </circle>
    </g>

</svg>

字体背景圆角效果

html 复制代码
<svg style="visibility: hidden; position: absolute;" width="0" height="0" xmlns="http://www.w3.org/2000/svg" version="1.1">
    <defs>
        <filter id="goo">
            <feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" />
            <feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 19 -9" result="goo" />
            <feComposite in="SourceGraphic" in2="goo" operator="atop"/>
        </filter>
    </defs>
</svg>

效果来自Gooey text background with SVG filters

结束语

关于feColorMatrix相关内容就先到这里啦,喜欢的朋友点点关注~

相关推荐
这里有鱼汤1 分钟前
无需HTML/CSS!用Python零基础打造专业级数据应用——Streamlit入门指南
前端·后端·python
Gazer_S5 分钟前
【行业树选择器组件:基于Vue3与Element Plus的高性能树形选择组件优化与重构】
前端·javascript·重构
白羊@20 分钟前
鸿蒙案例---生肖抽卡
前端·javascript·华为·harmonyos
橙某人26 分钟前
🍊🍊🍊在网格中进行拖动布局-Javascript、Vue
前端·javascript·vue.js
若川28 分钟前
Taro 4 已发布:11. Taro 是如何解析入口配置 app.config.ts 和页面配置的?
前端·javascript·微信小程序
八了个戒32 分钟前
「数据可视化 D3系列」入门第一章:Hello D3.js
开发语言·前端·javascript·数据可视化·canvas
Zhen (Evan) Wang39 分钟前
Margin和Padding在WPF和CSS中的不同
css·wpf
二川bro42 分钟前
深度解析 Vue 项目 Webpack 分包与合包 一文读懂
前端·vue.js·webpack
getapi43 分钟前
flutter底部导航代码解释
前端·javascript·flutter
nui1111 小时前
汽配快车道解决chrome backgroud.js(Service Worker) XMLHttpRequest is not defined问题
前端·javascript·chrome