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相关内容就先到这里啦,喜欢的朋友点点关注~

相关推荐
小二·15 分钟前
layui树形组件点击树节点后高亮的解决方案
前端·javascript·layui
Minions_Fatman17 分钟前
【layui】table的switch、edit修改
前端·javascript·layui
小孙姐33 分钟前
4——单页面应用程序,vue-cli脚手架
前端·javascript·vue.js
生椰拿铁You34 分钟前
15 —— Webpack中的优化——前端项目使用CDN技术
前端·webpack
生椰拿铁You34 分钟前
13 —— 开发环境调错-source map
前端
知野小兔1 小时前
【Angular】async详解
前端·javascript·angular.js
来啦来啦~1 小时前
vue项目实现动效交互---lottie动画库
前端·vue.js·交互
没了对象省了流量ii1 小时前
11.9K Star!强大的 Web 爬虫工具 FireCrawl:为 AI 训练与数据提取提供全面支持
前端·人工智能·爬虫
我的div丢了肿么办1 小时前
vue项目中如何加载markdown作为组件
前端·javascript·vue.js
南山十一少1 小时前
Spring Boot 实战:基于 Validation 注解实现分层数据校验与校验异常拦截器统一返回处理
java·前端·spring boot·后端