SVG feColorMatrix 标签

简介

该滤镜基于转换矩阵对颜色进行变换;
每一像素的颜色值(红,绿,蓝,透明度的矢量) 都经过矩阵乘法 (matrix multiplated) 计算出的新颜色。
就像 Photoshop 中通道编辑一样。

专有属性

属性 说明
in 输入的原语
type 矩阵操作的类型。分别有 matrix,saturate,hueRotate 和 luminanceToAlpha 四个值
values 根据 type 有不同的值,当 type=”matrix” 时由空格或者逗号分隔的20个矩阵值的列表,如果没指定该属性默认值是单位矩阵(从左上角到右下角的对角线上的元素均为1,除此以外全都为0);当 type=”saturate” 时是单个实数值(0到1),如果没指定该属性默认值是1;当 type=”hueRotate” 时是单个实数值 (角度),如果没指定该属性默认值是0;当 type=”luminanceToAlpha” 时是值不适用。

matrix 变换

matrix 类型是最专业的变换,其他的 type 模式(saturate、hueRotate 和 luminanceToAlpha)都是基于此矩阵变换得到,输入图像的每一个颜色值 RGBA 通过下面变换公式计算出新值实现颜色的转变;

首先变换矩阵是这样的(b1-b4 表示额外的偏移量):
$$
\left[\begin{array}{ccc}
a_1 & a_2 & a_3 & a_4 & b_1 \\
a_5 & a_6 & a_7 & a_8 & b_2 \\
a_9 & a_{10} & a_{11} & a_{12} & b_3 \\
a_{13} & a_{14} & a_{15} & a_{16} & b_4 \\
\end{array}\right]
$$

所以颜色换算公式是这样的,RGB 各部分的值越大,越趋向于白色,越小越倾向于黑色
$$
\begin{align}
& R = R \times a_1 + G \times a_2 + B \times a_3 + A \times a_4 + b_1 \\
& G = R \times a_5 + G \times a_6 + B \times a_7 + A \times a_8 + b_2 \\
& B = R \times a_9 + G \times a_{10} + B \times a_{11} + A \times a_{12} + b_3 \\
& A = R \times a_{13} + G \times a_{14} + B \times a_{15} + A \times a_{16} + b_4 \\
\end{align}
$$

又因为 matrix 的默认值是单位矩阵
$$\left[\begin{array}{ccc}
1 & 0 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 & 0 \\
0 & 0 & 1 & 0 & 0 \\
0 & 0 & 0 & 1 & 0 \\
\end{array}\right]
$$

所以

$$
\begin{align}
& R = R \times 1 + G \times 0 + B \times 0 + A \times 0 + 0 = R \\
& G = R \times 0 + G \times 1 + B \times 0 + A \times 0 + 0 = G \\
& B = R \times 0 + G \times 0 + B \times 1 + A \times 0 + 0 = B \\
& A = R \times 0 + G \times 0 + B \times 0 + A \times 1 + 0 = A \\
\end{align}
$$

可以看出经过和单位矩阵运算后颜色值是默认不变的,要改变颜色的效果我们看几个例子:

单通道颜色
只显示红色:我们想办法清空绿色和蓝色通道,让$ a_5 \sim a_{12} $的值为0就可以了,修改默认的矩阵如下
$$
\left[\begin{array}{ccc}
1 & 0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 & 0 \\
0 & 0 & 0 & 1 & 0 \\
\end{array}\right]
$$

同理只显示绿色(清空红色和蓝色通道)、蓝色(清空红色和绿色通道),得到变换矩阵分别是
$$
\left[\begin{array}{ccc}
0 & 0 & 0 & 0 & 0 \\
1 & 0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 & 0 \\
0 & 0 & 0 & 1 & 0 \\
\end{array}\right] \quad
\left[\begin{array}{ccc}
0 & 0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 & 0 \\
1 & 0 & 0 & 0 & 0 \\
0 & 0 & 0 & 1 & 0 \\
\end{array}\right]
$$

实例:

<svg width="100%" viewBox="0 0 400 100" preserveAspectRatio="xMidYMin meet" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <defs>
        <symbol id="sym01">
            <circle cx="30" cy="30" r="20" fill="blue" fill-opacity="0.5" />
            <circle cx="20" cy="50" r="20" fill="green" fill-opacity="0.5" />
            <circle cx="40" cy="50" r="20" fill="red" fill-opacity="0.5" />
        </symbol>
        <filter id="colorRed">
            <feColorMatrix in="SourceGraphic" type="matrix"
                  values="1 0 0 0 0
                          0 0 0 0 0
                          0 0 0 0 0
                          0 0 0 1 0" />
        </filter>
        <filter id="colorGreen">
            <feColorMatrix in="SourceGraphic" type="matrix"
                  values="0 0 0 0 0
                          1 0 0 0 0
                          0 0 0 0 0
                          0 0 0 1 0" />
        </filter>
        <filter id="colorBlue">
            <feColorMatrix in="SourceGraphic" type="matrix"
                           values="0 0 0 0 0
                                  0 0 0 0 0
                                  1 0 0 0 0
                                  0 0 0 1 0" />
        </filter>
    </defs>
    <use xlink:href="#sym01" x="0" y="0"/>
    <use xlink:href="#sym01" x="70" y="0" filter="url(#colorRed)"/>
    <use xlink:href="#sym01" x="140" y="0" filter="url(#colorGreen)"/>
    <use xlink:href="#sym01" x="210" y="0" filter="url(#colorBlue)"/>
    <text x="20" y="90" fill="green" font-size="8pt">原图</text>
    <text x="100" y="90" fill="green" font-size="8pt">红色</text>
    <text x="160" y="90" fill="green" font-size="8pt">绿色</text>
    <text x="240" y="90" fill="green" font-size="8pt">蓝色</text>
</svg>

效果:

混合颜色
上面例子是清空2个颜色通道,如果清空其中一个颜色通道,意味剩下2个通道,它们将会混合成一个新颜色,例如:

  • 清空蓝色通道,剩下红色+绿色通道=黄色
  • 清空绿色通道,剩下红色+蓝色通道=品红
  • 清空红色通道,剩下绿色+蓝色通道=青色

变换矩阵分别是:
$$
\left[\begin{array}{ccc}
1 & 0 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 & 0 \\
0 & 0 & 0 & 1 & 0 \\
\end{array}\right] \quad
\left[\begin{array}{ccc}
1 & 0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 & 0 \\
0 & 0 & 1 & 0 & 0 \\
0 & 0 & 0 & 1 & 0 \\
\end{array}\right] \quad
\left[\begin{array}{ccc}
0 & 0 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 & 0 \\
0 & 0 & 1 & 0 & 0 \\
0 & 0 & 0 & 1 & 0 \\
\end{array}\right]
$$

实例:

<svg width="100%" viewBox="0 0 400 100" preserveAspectRatio="xMidYMin meet" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <defs>
        <symbol id="sym01">
            <image x="10" y="10" xlink:href="https://s.tinyx.cc/images/common/avatar.png" />
        </symbol>
        <filter id="colorYellow">
            <feColorMatrix in="SourceGraphic" type="matrix"
                           values="1 0 0 0 0
                                  0 1 0 0 0
                                  0 0 0 0 0
                                  0 0 0 1 0" />
        </filter>
        <filter id="colorMagenta">
            <feColorMatrix in="SourceGraphic" type="matrix"
                           values="1 0 0 0 0
                                  0 0 0 0 0
                                  0 0 1 0 0
                                  0 0 0 1 0" />
        </filter>
        <filter id="colorCyan">
            <feColorMatrix in="SourceGraphic" type="matrix"
                           values="0 0 0 0 0
                                  0 1 0 0 0
                                  0 0 1 0 0
                                  0 0 0 1 0" />
        </filter>
    </defs>
    <use xlink:href="#sym01" x="0" y="0"/>
    <use xlink:href="#sym01" x="70" y="0" filter="url(#colorYellow)"/>
    <use xlink:href="#sym01" x="140" y="0" filter="url(#colorMagenta)"/>
    <use xlink:href="#sym01" x="210" y="0" filter="url(#colorCyan)"/>
    <text x="20" y="90" fill="green" font-size="8pt">原图</text>
    <text x="90" y="90" fill="green" font-size="8pt">黄色</text>
    <text x="160" y="90" fill="green" font-size="8pt">品红</text>
    <text x="240" y="90" fill="green" font-size="8pt">青色</text>
</svg>

效果:

亮度
通过调整每个通道值大小实现,值越大越亮,例如我们调亮(每个通道值改成 2),调暗(每个通道值改成 0.5)
$$
\left[\begin{array}{ccc}
2 & 0 & 0 & 0 & 0 \\
0 & 2 & 0 & 0 & 0 \\
0 & 0 & 2 & 0 & 0 \\
0 & 0 & 0 & 1 & 0 \\
\end{array}\right] \quad
\left[\begin{array}{ccc}
0.5 & 0 & 0 & 0 & 0 \\
0 & 0.5 & 0 & 0 & 0 \\
0 & 0 & 0.5 & 0 & 0 \\
0 & 0 & 0 & 1 & 0 \\
\end{array}\right]
$$

<svg width="100%" viewBox="0 0 400 100" preserveAspectRatio="xMidYMin meet" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <defs>
        <symbol id="sym01">
            <circle cx="30" cy="30" r="20" fill="blue" fill-opacity="0.5" />
            <circle cx="20" cy="50" r="20" fill="green" fill-opacity="0.5" />
            <circle cx="40" cy="50" r="20" fill="red" fill-opacity="0.5" />
        </symbol>
        <filter id="lighten">
            <feColorMatrix in="SourceGraphic" type="matrix"
                           values="5 0 0 0 0
                                  0 5 0 0 0
                                  0 0 5 0 0
                                  0 0 0 1 0" />
        </filter>
        <filter id="darken">
            <feColorMatrix in="SourceGraphic" type="matrix"
                           values="0.1 0 0 0 0
                                  0 0.1 0 0 0
                                  0 0 0.1 0 0
                                  0 0 0 1 0" />
        </filter>
    </defs>
    <use xlink:href="#sym01" x="0" y="0"/>
    <use xlink:href="#sym01" x="70" y="0" filter="url(#lighten)"/>
    <use xlink:href="#sym01" x="140" y="0" filter="url(#darken)"/>
    <text x="20" y="90" fill="green" font-size="8pt">原图</text>
    <text x="85" y="90" fill="green" font-size="8pt">更光</text>
    <text x="150" y="90" fill="green" font-size="8pt">更暗</text>
</svg>

效果:

灰度
将某一列有相同的值,将会过滤出灰度效果
$$
\left[\begin{array}{ccc}
1 & 0 & 0 & 0 & 0 \\
1 & 0 & 0 & 0 & 0 \\
1 & 0 & 0 & 0 & 0 \\
0 & 0 & 0 & 1 & 0 \\
\end{array}\right] \quad
\left[\begin{array}{ccc}
0 & 1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 & 0 \\
0 & 0 & 0 & 1 & 0 \\
\end{array}\right] \quad
\left[\begin{array}{ccc}
0 & 0 & 1 & 0 & 0 \\
0 & 0 & 1 & 0 & 0 \\
0 & 0 & 1 & 0 & 0 \\
0 & 0 & 0 & 1 & 0 \\
\end{array}\right]
$$

实例:

<svg width="100%" viewBox="0 0 400 100" preserveAspectRatio="xMidYMin meet" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <defs>
        <symbol id="sym01">
            <image x="10" y="10" xlink:href="https://s.tinyx.cc/images/common/avatar.png" />
        </symbol>
        <filter id="grayOnLight">
            <feColorMatrix in="SourceGraphic" type="matrix"
                           values="1 0 0 0 0
                                  1 0 0 0 0
                                  1 0 0 0 0
                                  0 0 0 1 0" />
        </filter>
        <filter id="grayOnMid">
            <feColorMatrix in="SourceGraphic" type="matrix"
                           values="0 1 0 0 0
                                  0 1 0 0 0
                                  0 1 0 0 0
                                  0 0 0 1 0" />
        </filter>
         <filter id="grayOnDark">
                <feColorMatrix in="SourceGraphic" type="matrix"
                           values="0 0 1 0 0
                                  0 0 1 0 0
                                  0 0 1 0 0
                                  0 0 0 1 0" />
        </filter>
    </defs>
    <use xlink:href="#sym01" x="0" y="0"/>
    <use xlink:href="#sym01" x="70" y="0" filter="url(#grayOnLight)"/>
    <use xlink:href="#sym01" x="140" y="0" filter="url(#grayOnMid)"/>
    <use xlink:href="#sym01" x="210" y="0" filter="url(#grayOnDark)"/>
    <text x="20" y="90" fill="green" font-size="6pt">原图</text>
    <text x="85" y="90" fill="green" font-size="6pt">亮灰</text>
    <text x="155" y="90" fill="green" font-size="6pt">中灰</text>
    <text x="225" y="90" fill="green" font-size="6pt">黑灰</text>
</svg>

效果:

透明度
每个通道是最后一列的数字,值的范围从 0-1,如果完全透明则给负数,具体多少实际一般 -1 到 -4 左右,以下实验看结果:
实例:

<svg width="100%" viewBox="0 0 500 100" preserveAspectRatio="xMidYMin meet" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <defs>
        <symbol id="sym01">
            <circle cx="30" cy="30" r="20" fill="blue" fill-opacity="0.5" />
            <circle cx="20" cy="50" r="20" fill="green" fill-opacity="0.5" />
            <circle cx="40" cy="50" r="20" fill="red" fill-opacity="0.5" />
        </symbol>
        <filter id="alphaHalf">
            <feColorMatrix in="SourceGraphic" type="matrix"
                           values="1 0 0 0 0
                                  0 1 0 0 0
                                  0 0 1 0 0
                                  0 0 0 0.5 0" />
        </filter>
        <filter id="alphaDouble">
            <feColorMatrix in="SourceGraphic" type="matrix"
                           values="1 0 0 0 0
                                  0 1 0 0 0
                                  0 0 1 0 0
                                  0 0 0 2 0" />
        </filter>
        <filter id="hideRed">
            <feColorMatrix in="SourceGraphic" type="matrix"
                           values="1 0 0 0 0
                                  0 1 0 0 0
                                  0 0 1 0 0
                                  -2 0 0 1 0" />
        </filter>
        <filter id="hideGreen">
            <feColorMatrix in="SourceGraphic" type="matrix"
                           values="1 0 0 0 0
                                  0 1 0 0 0
                                  0 0 1 0 0
                                  0 -4 0 1 0" />
        </filter>
        <filter id="hideBlue">
            <feColorMatrix in="SourceGraphic" type="matrix"
                           values="1 0 0 0 0
                                  0 1 0 0 0
                                  0 0 1 0 0
                                  0 0 -4 1 0" />
        </filter>
    </defs>
    <use xlink:href="#sym01" x="0" y="0"/>
    <use xlink:href="#sym01" x="70" y="0" filter="url(#alphaHalf)"/>
    <use xlink:href="#sym01" x="140" y="0" filter="url(#alphaDouble)"/>
    <use xlink:href="#sym01" x="210" y="0" filter="url(#hideRed)"/>
    <use xlink:href="#sym01" x="280" y="0" filter="url(#hideGreen)"/>
    <use xlink:href="#sym01" x="350" y="0" filter="url(#hideBlue)"/>
    <text x="20" y="90" fill="green" font-size="6pt">原图</text>
    <text x="85" y="90" fill="green" font-size="6pt">增加透明</text>
    <text x="155" y="90" fill="green" font-size="6pt">减少透明</text>
    <text x="225" y="90" fill="green" font-size="6pt">红色透明</text>
    <text x="295" y="90" fill="green" font-size="6pt">绿色透明</text>
    <text x="365" y="90" fill="green" font-size="6pt">蓝色透明</text>
</svg>

效果:

其他 type 模式

都很好理解

  • saturate:调整饱和度(0~1,颜色越大越饱和)
  • hueRotate:色相旋转。用 0-360 度表达;
  • luminanceToAlpha:将每个通道的亮度变成 alpha 通道值,然后显示(只显示 alpha 通道)

实例:

<svg width="100%" height="100%" viewBox="0 0 360 300" preserveAspectRatio="xMidYMin meet" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <defs>
        <symbol id="sym01">
            <circle cx="30" cy="30" r="20" fill="blue" fill-opacity="0.5" />
            <circle cx="20" cy="50" r="20" fill="green" fill-opacity="0.5" />
            <circle cx="40" cy="50" r="20" fill="red" fill-opacity="0.5" />
        </symbol>
        <filter id="colorMeMatrix">
            <feColorMatrix in="SourceGraphic" type="matrix"
              values="0 0 0 0 0
                  1 1 1 1 1
                  0 0 0 0 0
                  0 0 0 1 0" />
        </filter>
        <filter id="colorMeSaturate">
            <feColorMatrix in="SourceGraphic" type="saturate" values="0.2" />
        </filter>
        <filter id="colorMeHueRotate">
            <feColorMatrix in="SourceGraphic" type="hueRotate" values="180" />
        </filter>
        <filter id="colorMeLTA">
            <feColorMatrix in="SourceGraphic" type="luminanceToAlpha" />
        </filter>
    </defs>
    <use xlink:href="#sym01" x="0" y="0"/>
    <use xlink:href="#sym01" x="70" y="0" filter="url(#colorMeMatrix)"/>
    <use xlink:href="#sym01" x="140" y="0" filter="url(#colorMeSaturate)"/>
    <use xlink:href="#sym01" x="210" y="0" filter="url(#colorMeHueRotate)"/>
    <use xlink:href="#sym01" x="280" y="0" filter="url(#colorMeLTA)"/>
    <text x="10" y="90" fill="green" font-size="8pt">原图</text>
    <text x="80" y="90" fill="green" font-size="8pt">矩阵</text>
    <text x="150" y="90" fill="green" font-size="8pt">饱和度</text>
    <text x="210" y="90" fill="green" font-size="8pt">颜色旋转</text>
    <text x="280" y="90" fill="green" font-size="7pt">luminanceToAlpha</text>
</svg>

效果:

留下评论

电子邮件地址不会被公开。 必填项已用*标注