前言
CSS 已经为我们内置了平移(translate),缩放(scale),旋转(rotate)和斜切(skew)相关的AP了。如果单单从使用来说,这些API已经足够我们使用了。那么按理说,我们已经没有必要去深入研究了,但是只是知其然,而不知其所以然,总是不够的,而且CSS还专门提供了一个matrix的API,那么我们就一起来探究探究把。
一、2D平面的矩阵由来?
我们的2D平面坐标系,仅仅有x,y两个坐标体系,那么不管我们怎么对图片进行变换,归根结底都是对x,y 坐标的变换。
对于二维我们使用的是一个3x3的矩阵,类似这样:
(
a
b
c
d
e
f
g
h
i
)
\begin{pmatrix} a & b &c \\ d & e &f \\ g & h & i \end{pmatrix}
⎝⎛adgbehcfi⎠⎞
在计算的时候我们以该矩阵乘以我们的位置矩阵,因为二维当中只有x,y两个值。但要进行计算需要3个值,所以我们将第3个值设置为1。就可以的到我们的位置矩阵:
(
x
y
1
)
\begin{pmatrix} x \\ y \\ 1 \end{pmatrix}
⎝⎛xy1⎠⎞
在该例中,即是:
{
n
e
w
X
=
a
∗
x
+
b
∗
y
+
c
∗
1
n
e
w
Y
=
d
∗
x
+
e
∗
y
+
f
∗
1
e
x
t
r
a
=
g
∗
x
+
h
∗
y
+
i
∗
1
①
\begin{cases} newX=a*x+b*y+c*1 \\ newY=d*x+e*y+f*1 \\ extra=g*x+h*y+i*1 \end{cases} ①
⎩⎪⎨⎪⎧newX=a∗x+b∗y+c∗1newY=d∗x+e∗y+f∗1extra=g∗x+h∗y+i∗1①
好像单从这里也看不出来什么,下面我们来一步一步的使用矩阵完成CSS API中的平移,缩放,旋转,斜切吧,从中你就应该有所体会了。
二、平移
假设我们需要对2D平面中一个点(x,y)进行平移,平移的量为tx,ty,得到新点的坐标(x1,y1)。
公式推导
因为只是简单的移动x,y轴,所以:
{
x
1
=
x
+
t
x
y
1
=
y
+
t
y
②
\begin{cases} x_1=x+tx \\ y_1=y+ty \end{cases} ②
{x1=x+txy1=y+ty②
推导矩阵
由①据②可得各参数取值:
{
a
=
1
b
=
0
c
=
t
x
d
=
0
e
=
1
f
=
t
y
\begin{cases} a=1 \\ b=0 \\ c=tx \\ d=0 \\ e=1 \\ f=ty \end{cases}
⎩⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎧a=1b=0c=txd=0e=1f=ty
因为只需关注x,y,所以可取得我们的一个平移矩阵:
(
1
0
t
x
0
1
t
y
0
0
1
)
\begin{pmatrix} 1 & 0 &tx \\ 0 & 1 &ty \\ 0 & 0 & 1 \end{pmatrix}
⎝⎛100010txty1⎠⎞
从这里可以看出,影响我们平移x,y变化的在矩阵中红框中的位置:
三、缩放
假设我们需要对2D平面中坐标原点到一个点A(x,y)所在的线段进行缩放,缩放的比例为z,那么A对应的新点的坐标B(x1,y1)。
公式推导
因为只是简单的缩放x,y轴,所以:
{
x
1
=
x
∗
z
y
1
=
y
∗
z
③
\begin{cases} x_1=x*z \\ y_1=y*z \end{cases} ③
{x1=x∗zy1=y∗z③
推导矩阵
由①据③可得各参数取值:
{
a
=
z
b
=
0
c
=
0
d
=
0
e
=
z
f
=
0
\begin{cases} a=z \\ b=0 \\ c=0 \\ d=0 \\ e=z \\ f=0 \end{cases}
⎩⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎧a=zb=0c=0d=0e=zf=0
因为只需关注x,y,所以可取得我们的一个缩放矩阵:
(
z
0
0
0
z
0
0
0
1
)
\begin{pmatrix} z & 0 &0 \\ 0 &z&0 \\ 0 & 0 & 1 \end{pmatrix}
⎝⎛z000z0001⎠⎞
从这里可以看出,影响我们旋转变化的在矩阵中红框中的位置:
四、旋转
假设我们需要对2D平面中一个点(x,y)围绕坐标原点进行旋转,旋转的角度为β,得到新点的坐标(x1,y1)。
要得到新点的坐标,首先我们需要理解一个概念:
单位圆
- 在平面直角坐标系中,圆心在原点,半径为1的圆即是我们的单位圆。
- 由1,当我们已经一个点的与圆心的连线的角度时(假设为α),那么我们可以求得他的坐标为(cos(α),sin(a))。
- 由2,现在我们把这个单位圆扩展到以坐标原点为圆心,半径为r的圆上任意一点。假设一点的偏转角度为α,那么得出该坐标为(r * cos(α),r * sin(a))
公式推导
由单位圆的概念,假定我们要移动的点(x,y)与坐标原点构成的半径为r的圆中,该点的偏转角度为a,那么把该点旋转β度之后,得到的新点(x1,y1)的坐标旋转角度应该是(α+β)度,由此我们可得到一个公式:
{
x
=
r
∗
c
o
s
(
α
)
y
=
r
∗
s
i
n
(
α
)
x
1
=
r
∗
c
o
s
(
α
+
β
)
=
r
∗
c
o
s
α
c
o
s
β
−
r
∗
s
i
n
α
s
i
n
β
y
1
=
r
∗
s
i
n
(
α
+
β
)
=
r
∗
s
i
n
(
α
)
c
o
s
(
β
)
+
r
∗
c
o
s
(
α
)
s
i
n
(
β
)
\begin{cases} x= r * cos(α) \\ y= r * sin(α) \\ x_1= r * cos(α+β) =r*cosαcosβ-r*sinαsinβ\\ y_1= r * sin(α+β) =r * sin(α) cos(β)+r*cos(α)sin(β) \end{cases}
⎩⎪⎪⎪⎨⎪⎪⎪⎧x=r∗cos(α)y=r∗sin(α)x1=r∗cos(α+β)=r∗cosαcosβ−r∗sinαsinβy1=r∗sin(α+β)=r∗sin(α)cos(β)+r∗cos(α)sin(β)
简化得到:
{
x
1
=
x
∗
c
o
s
β
−
y
∗
s
i
n
β
y
1
=
x
∗
s
i
n
(
β
)
+
y
∗
c
o
s
(
β
)
④
\begin{cases} x_1= x*cosβ-y*sinβ\\ y_1= x*sin(β) +y*cos(β) \end{cases} ④
{x1=x∗cosβ−y∗sinβy1=x∗sin(β)+y∗cos(β)④
推导矩阵
由①据④可得各参数取值:
{
a
=
c
o
s
(
β
)
b
=
−
s
i
n
(
β
)
c
=
0
d
=
s
i
n
(
β
)
e
=
c
o
s
(
β
)
f
=
0
\begin{cases} a= cos(β)\\ b=-sin(β) \\ c=0\\ d=sin(β) \\ e=cos(β) \\ f=0 \end{cases}
⎩⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎧a=cos(β)b=−sin(β)c=0d=sin(β)e=cos(β)f=0
因为只需关注x,y,所以可取得我们的一个旋转矩阵:
(
c
o
s
(
β
)
−
s
i
n
(
β
)
0
s
i
n
(
β
)
c
o
s
(
β
)
0
0
0
1
)
\begin{pmatrix} cos(β) & -sin(β) &0 \\ sin(β) &cos(β)&0 \\ 0 & 0 & 1 \end{pmatrix}
⎝⎛cos(β)sin(β)0−sin(β)cos(β)0001⎠⎞
从这里可以看出,影响我们旋转变化的在矩阵中红框中的位置:
五、斜切
假设我们需要对2D平面中一个点A(x,y)分别延X轴斜切α角度,延Y轴倾斜β角度,所得新点B(x1,y1)。
要得到新点的坐标,首先我们需要理解一个概念:
斜切的概念
-
X轴斜切
- 如果我们要把一个点延X轴方向斜切,即该点的Y轴坐标不变,X轴坐标为 该点的X轴坐标 加上以坐标原点到该点半径为r的圆中,所得倾斜角度在该圆中的y坐标的值。 Y轴斜切
- 如果我们要把一个点延Y轴方向斜切,即该点的X轴坐标不变,Y轴坐标为 该点的Y轴坐标 加上以坐标原点到该点半径为r的圆中,所得倾斜角度在该圆中的y坐标的值。
公式推导
由四部分的内容根据斜切的概念,得到新点B:
{
x
1
=
x
+
y
∗
t
a
n
(
α
)
y
1
=
y
+
x
∗
t
a
n
(
β
)
⑤
\begin{cases} x_1=x+y*tan(α) \\ y_1= y+x*tan(β) \end{cases} ⑤
{x1=x+y∗tan(α)y1=y+x∗tan(β)⑤
由①据⑤可得各参数取值:
{
a
=
1
b
=
t
a
n
(
α
)
c
=
0
d
=
t
a
n
(
β
)
e
=
1
f
=
0
\begin{cases} a= 1\\ b=tan(α) \\ c=0\\ d=tan(β)\\ e=1 \\ f=0 \end{cases}
⎩⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎧a=1b=tan(α)c=0d=tan(β)e=1f=0
因为只需关注x,y,所以可取得我们的一个旋转矩阵:
(
1
t
a
n
(
α
)
0
t
a
n
(
β
)
1
0
0
0
1
)
\begin{pmatrix} 1 & tan(α)&0 \\ tan(β) &1&0 \\ 0 & 0 & 1 \end{pmatrix}
⎝⎛1tan(β)0tan(α)10001⎠⎞
从这里可以看出,影响我们斜切变化的在矩阵中红框中的位置(X轴斜切由tan(α)的值影响,Y轴斜切由tan(β)位置的值影响):
六、CSS3中matrix() 使用
到这里,你应该对CSS中的矩阵有了一个比较清晰的理解了。那么我们来看下CSS中的matrix。
可以发现,matrix() API 中,仅仅有6个参数,不是有9个吗?怎么只有6个,其实本身是9个,只不过最后一行用了默认值处理,并对我们做了隐藏。
还记得我们最开始的那个矩阵吗?
(
a
b
c
d
e
f
g
h
i
)
\begin{pmatrix} a & b &c \\ d & e &f \\ g & h & i \end{pmatrix}
⎝⎛adgbehcfi⎠⎞
这里注意一点,我们前文所有的矩阵,对应到Web中的矩阵来说,你可能都感觉有点怪,主要原因就是,数学中的矩阵和Web中的矩阵有点差异。
下面是正常数学中的矩阵:
可见行是横向的,列是纵向的。
而Web中呢:
所以前文的矩阵结果对应到matrix来说,就为matrix(a, d, b, e, c, f)。
可以简单记为:
matrix( scaleX(), skewY(), skewX(), scaleY(), translateX(), translateY() )
总结
到这里我们就把Web中2D矩阵介绍完了,当然大部分情况下,我们可能都不一定会用这个API,用的更多的可能还是translate(),scale(),skewY(),rotate()这些更明确的方法。不过我们要进一步提高自己的技术,还是应该知其然,也知其所以然。