共计 3027 个字符,预计需要花费 8 分钟才能阅读完成。
关于 Matrix
我们先看看 chatGpt 是如何介绍矩阵的。
矩阵是数学中的一个概念,它是由数字按照矩形排列而成的矩形阵列。矩阵由行和列组成,行表示矩阵的水平方向,列表示矩阵的垂直方向。
一个矩阵可以用以下形式表示:
A = [a11, a12, a13, ..., a1n]
[a21, a22, a23, ..., a2n]
[a31, a32, a33, ..., a3n]
...
[am1, am2, am3, ..., amn]
其中,a11, a12, a13, ..., a1n
表示第一行的元素,a21, a22, a23, ..., a2n
表示第二行的元素,以此类推,am1, am2, am3, ..., amn
表示第 m 行的元素。
矩阵的大小由行数和列数决定,如果一个矩阵有 m 行和 n 列,我们称其为 m×n 的矩阵。
矩阵在数学和计算机科学中有广泛的应用,例如线性代数、图形学、机器学习等领域。矩阵可以进行加法、减法、乘法等运算,还可以表示向量、线性方程组、线性变换等概念。
在 CSS 中,矩阵也被用于表示 2D 变换效果,如平移、缩放、旋转和错切等。通过矩阵的乘法运算,可以将多个变换效果组合在一起,实现复杂的变换效果。
CSS3 transform 的 matrix()
transform: matrix(a,b,c,d,e,f);
实际上,这 6 参数,对应的矩阵就是:
注意书写方向是竖着的。
假如矩阵要变化,例如偏移,旋转或者变形或者其他的中心点是 xy,那么矩阵变化如下
其中,x, y 表示转换元素的所有坐标(变量)了。那后面的 ax+cy+ e 怎么来的呢?
很简单,3 3 矩阵每一行的第 1 个值与后面 1 3 的第 1 个值相乘,第 2 个值与第 2 个相乘,第 3 个与第 3 个,然后相加,如下图同色标注:
那 ax+cy+ e 的意义是什么?
ax+cy+ e 为变换后的水平坐标,
bx+dy+ f 表示变换后的垂直位置。
矩阵偏移
关于偏移,假如是如下矩阵
transform: matrix(1, 0, 0, 1, 60, 60); /* a=1, b=0, c=0, d=1, e=60, f=60 */
现在,我们根据这个矩阵偏移元素的中心点,假设是(0, 0),即 x =0, y=0。
于是,变换后的
x 坐标就是 ax+cy+e = 10+00+60 =60,
y 坐标就是 bx+dy+f = 00+10+60 =60.
于是,中心点坐标从 (0, 0) 变成了→(60, 60)。
也就是相当于
transform: translate(60px, 60px);
注意:translate, rotate 等方法都是需要单位的,而 matrix 方法 e, f 参数的单位可以省略。
矩阵缩放(scale)
发现没,matrix(1, 0, 0, 1, 60, 60); 的元素比例与原来一样,1:1, 而这几个参数中,有两个 1,
没错,这两个 1 就是缩放相关的参数。
其中,第一个缩放 x 轴,第二个缩放 y 轴。
用公式就很明白了,假设比例是 s,则有 matrix(s, 0, 0, s, 0, 0);,于是,套用公式,就有:
x’ = ax+cy+e = sx+0y+0 = s*x;
y’ = bx+dy+f = 0x+sy+0 = s*y;
也就是
matrix(sx, 0, 0, sy, 0, 0);
,等同于
scale(sx, sy);
矩阵旋转(rotate)
旋转相比前面两个要更高级些,要用到三角函数。
方法以及参数使用如下(假设角度为 θ):
matrix(cosθ,sinθ,-sinθ,cosθ,0,0)
结合矩阵公式,就有:
x' = x*cosθ-y*sinθ+0 = x*cosθ-y*sinθ
y' = x*sinθ+y*cosθ+0 = x*sinθ+y*cosθ
假如
transform:rotate(30deg);
转换成矩阵就是
transform: matrix(0.866025,0.500000,-0.500000,0.866025,0,0);
矩阵拉伸(skew)
拉伸也用到了三角函数,不过是 tanθ,而且,其至于 b, c 两个参数相关,书写如下(注意 y 轴倾斜角度在前):
matrix(1,tan(θy),tan(θx),1,0,0)
对应公式如下:
x' = x+y*tan(θx)+0 = x+y*tan(θx)
y' = x*tan(θy)+y+0 = x*tan(θy)+y
对应于 skew(θx + “deg”,θy+ “deg”)这种写法。
其中,θx 表示 x 轴倾斜的角度,θy 表示 y 轴,两者并无关联。
矩阵 matrix 实现镜像渐变
镜像主要是指 transform 里面其他属性实现不了的功能,轴围绕的那个点就是 CSS3 中 transform 变换的中心点,
因为该轴永远经过原点,因此,任意对称轴都可以用 y = k * x 表示。则 matrix 表示就是:
matrix((1-k*k) / (1+k*k), 2k / (1 + k*k), 2k / (1 + k*k), (k*k - 1) / (1+k*k), 0, 0)
这个如何得到的呢?
一是垂直,二是中心点在轴线上,因此有:
(y-y') / (x - x') = -1/ k → ky-ky'= -x+x'
(x + x') / 2 * k = (y + y')/2 → kx+kx'= y+y'
很简单的,把 x ’ 和 y ’ 提出来,就有:
x' = (1-k*k)/(k*k+1) *x + 2k/(k*k+1) *y;
y' = 2k/(k*k+1) *x + (k*k-1)/(k*k+1) *y;
再结合矩阵公式:
x' = ax+cy+e;
y' = bx+dy+f;
我们就可以得到:
a = (1-k*k)/(k*k+1);
b = 2k/(k*k+1);
c = 2k/(k*k+1);
d = (k*k-1)/(k*k+1);
也就是上面 matrix 方法中的参数值啦!
3D 变换中的矩阵
3D 变换虽然只比 2D 多了一个 D,但是复杂程度不只多了一个。从二维到三维,是从 4 到 9;而在矩阵里头是从 3 3 变成 4 4, 9 到 16 了。
其实,本质上很多东西都与 2D 一致的,只是复杂度不一样而已。这里就举一个简单的 3D 缩放变换的例子。
transform: matrix3d(sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, sz, 0, 0, 0, 0, 1)
psd.js 里面的字体矩阵旋转
psd.js 解析的字体如下:
transform: {
tx: 243.2087255915381,
ty: 662.7336218363249,
xx: 0.3848003848003848,
xy: 0,
yx: 0,
yy: 0.38469353200135453,
}
要将这些属性值转换为 CSS 中的 matrix
,可以按照以下方式进行计算:
const transform = {
tx: 243.2087255915381,
ty: 662.7336218363249,
xx: 0.3848003848003848,
xy: 0,
yx: 0,
yy: 0.38469353200135453,
};
const matrixValue = `matrix(${transform.xx}, ${transform.xy}, ${transform.yx}, ${transform.yy}, ${transform.tx}, ${transform.ty})`;
console.log(matrixValue);
在上面的代码中,我们使用 transform
对象中的属性值构建了 matrix
字符串。${transform.xx}
表示水平方向上的缩放比例,${transform.xy}
表示水平方向上的错切值,${transform.yx}
表示垂直方向上的错切值,${transform.yy}
表示垂直方向上的缩放比例,${transform.tx}
表示水平方向上的平移量,${transform.ty}
表示垂直方向上的平移量。