从matrix变换函数矩阵来说明CSS Transform的原理和操作

文章以二维变换为例说明,三维变换采用类似的操作理解即可。

变换的坐标系统

默认的变换坐标系统,变换原点为元素中心,x轴与y轴与web中定义的一致。其中,变换原点可以用transform-origin属性来设置。transform是以该坐标系统为参考,对变换中图形上每个点的坐标进行更新,来得到变换后的图形。

线性变换

线性变换需要满足两个条件:

  1. 不改变坐标原点
  2. 每个点的坐标在更新时,采用线性函数来更新。用数学中的线性方程表达如下 { x ′ = a x + c y y ′ = b x + d y \begin{cases}x\prime =&ax+cy\\ y\prime =&bx+dy\end{cases} {x=y=ax+cybx+dy
    用矩阵的形式表示为 [ x ′ y ′ ] = [ a c b d ] [ x y ] \begin{bmatrix}x\prime \\ y\prime \end{bmatrix} =\begin{bmatrix}a&c\\ b&d\end{bmatrix} \begin{bmatrix}x\\ y\end{bmatrix} [xy]=[abcd][xy]
    CSS Transform中,除了translate变换外,其他都属于线性变换。因此,除了translate外,其他变换可以用2*2的矩阵描述如下 [ a c b d ] \begin{bmatrix}a&c\\ b&d\end{bmatrix} [abcd],而translate变换需要额外描述,因此CSS Transform的矩阵描述如下 [ a c e b d f 0 0 1 ] \begin{bmatrix}a&c&e\\ b&d&f\\ 0&0&1\end{bmatrix} ab0cd0ef1其中, [ a c e b d f ] \begin{bmatrix}a&c&e\\ b&d&f\end{bmatrix} [abcdef]其实足够描述二维变换了,最后一行是为了矩阵运算而补充的。e和f就是为了translate而增加的额外描述,e用来描述translateX,f用来描述translateY。

matrix()函数

CSS Transform中的所有变换,实际上都是matrix()函数的封装,为了便于记忆和使用。在二维变换中,matrix()函数接收6个参数为matrix(a, b, c, d, e, f),即为上文中的矩阵元素。matrix()函数本质上就是上文中的变换矩阵,对于不同的变换,6个参数各不相同。
下列变换中,假设没有变换时,图形上点的坐标为(x, y),变换后为(x’, y’)。为了方便运算,点的坐标额外增加一行为1;

没有变换

matrix矩阵为 [ 1 0 0 0 1 0 0 0 1 ] \begin{bmatrix}1&0&0\\ 0&1&0\\ 0&0&1\end{bmatrix} 100010001,为一个3*3的单位矩阵。因此,所有点的坐标没有任何变化。

translate变换

translate变换只是给e和f赋值,其中translateX()给e赋值,translateY()给f赋值,此时matrix矩阵为 [ 1 0 e 0 1 f 0 0 1 ] \begin{bmatrix}1&0&e\\ 0&1&f\\ 0&0&1\end{bmatrix} 100010ef1
变换的过程表示为 [ x ′ y ′ 1 ] = [ 1 0 e 0 1 f 0 0 1 ] [ x y 1 ] \begin{bmatrix}x\prime \\ y\prime \\ 1\end{bmatrix} =\begin{bmatrix}1&0&e\\ 0&1&f\\ 0&0&1\end{bmatrix} \begin{bmatrix}x\\ y\\ 1\end{bmatrix} xy1=100010ef1xy1线性方程为
{ x ′ = x + e y ′ = y + f \begin{cases}x\prime =&x+e\\ y\prime =&y+f\end{cases} {x=y=x+ey+f
可以看出,translate变换相当于在原来坐标系统下,每个点的x坐标增加e,y坐标增加f,得到了新的坐标。

改变坐标原点的理解:也可以这样理解,让e和f都等于0,此时每个点的坐标都不变,而坐标系统的原点从(0, 0)移动到了(e, f)。从这个角度来看,translate改变了坐标原点的位置。也就是说,原来的图形坐标都不用变,只要把坐标原点移动到(e, f)的位置即可。注意:(e, f)这个位置坐标是以原坐标系统为参考点的。用这种方式理解的前提是,原来的坐标系统用来定位新的坐标系统,新的坐标系统用来定位图形的坐标。
rotate变换

rotate()变换是指围绕原点,旋转某个角度α,正数表示顺时针旋转,负数表示逆时针旋转。对应于matrix矩阵,指的是 [ c o s α − s i n α 0 s i n α c o s α 0 0 0 1 ] \begin{bmatrix}cos\alpha &-sin\alpha &0\\ sin\alpha &cos\alpha &0\\ 0&0&1\end{bmatrix} cosαsinα0sinαcosα0001变换的过程表示为 [ x ′ y ′ 1 ] = [ c o s α − s i n α 0 s i n α c o s α 0 0 0 1 ] [ x y 1 ] \begin{bmatrix}x\prime \\ y\prime \\ 1\end{bmatrix} =\begin{bmatrix}cos\alpha &-sin\alpha &0\\ sin\alpha &cos\alpha &0\\ 0&0&1\end{bmatrix} \begin{bmatrix}x\\ y\\ 1\end{bmatrix} xy1=cosαsinα0sinαcosα0001xy1线性方程为 { x ′ = x cos ⁡ α − y sin ⁡ α y ′ = x sin ⁡ α + y cos ⁡ α \begin{cases}x\prime =&x\cos \alpha -y\sin \alpha \\ y\prime =&x\sin \alpha +y\cos \alpha \end{cases} {x=y=xcosαysinαxsinα+ycosα
可以看出,旋转变换是对x和y坐标进行三角函数运算

scale变换

scale()变换是指对图形的缩放,按照某个比例放大或缩小图形。缩放是对x轴和y轴坐标刻度的更改,因此对应于matrix矩阵,指的是 [ a 0 0 0 d 0 0 0 1 ] \begin{bmatrix}a&0&0\\ 0&d&0\\ 0&0&1\end{bmatrix} a000d0001a表示x轴的缩放比例,d表示y轴的缩放比例。变换的过程为 [ x ′ y ′ 1 ] = [ a 0 0 0 d 0 0 0 1 ] [ x y 1 ] \begin{bmatrix}x\prime \\ y\prime \\ 1\end{bmatrix} =\begin{bmatrix}a&0&0\\ 0&d&0\\ 0&0&1\end{bmatrix} \begin{bmatrix}x\\ y\\ 1\end{bmatrix} xy1=a000d0001xy1线性方程为 { x ′ = a x y ′ = d y \begin{cases}x\prime =&ax\\ y\prime =&dy\end{cases} {x=y=axdy可以看出,的确是将x坐标乘以a,将y坐标乘以d。

skew变换

skew()变换指的是将图形的水平线或垂直线做一定程度的倾斜,即看起来变歪了。由于倾斜涉及到角度,因此matrix矩阵为 [ 1 tan ⁡ θ x 0 tan ⁡ θ y 1 0 0 0 1 ] \begin{bmatrix}1&\tan \theta_{x} &0\\ \tan \theta_{y} &1&0\\ 0&0&1\end{bmatrix} 1tanθy0tanθx10001其中,θx和θy分别为skewX()和skewY()的参数,θx表示垂直线倾斜角(正数表示向x轴正半轴倾斜),θy表示水平线倾斜角(正数表示向y轴正半轴倾斜)。这一点从线性方程中可以看出。变换过程为 [ x ′ y ′ 1 ] = [ 1 tan ⁡ θ x 0 tan ⁡ θ y 1 0 0 0 1 ] [ x y 1 ] \begin{bmatrix}x\prime \\ y\prime \\ 1\end{bmatrix} =\begin{bmatrix}1&\tan \theta_{x} &0\\ \tan \theta_{y} &1&0\\ 0&0&1\end{bmatrix} \begin{bmatrix}x\\ y\\ 1\end{bmatrix} xy1=1tanθy0tanθx10001xy1线性方程为 { x ′ = x + y tan ⁡ θ x y ′ = y + x tan ⁡ θ y \begin{cases}x\prime =&x+y\tan \theta_{x} \\ y\prime =&y+x\tan \theta_{y} \end{cases} {x=y=x+ytanθxy+xtanθy从中可以看出,x和y坐标都是在原来基础上,增加了一部分由角度决定的量,结果就是变歪了。

复合变换

这里的复合变换,指的是一个transform属性中,包含以上几个变换,由以上几个变换按顺序组成。这里的顺序非常重要,因为顺序不同,最后得到的matrix矩阵会不同。尤其在包含translate变换的情况下,因为translate的非线性,导致的变换差异很大。
复合变换的规则是,transform属性中,按从左向右的顺序,将代表各个变换的matrix矩阵依次相乘,得到最终的matrix矩阵。由于矩阵乘法不满足交换律,因此这里的顺序很重要。另外,translate如果放在其他变换的右边,其他变换就会连translate变换一起变换。听起来很乱吧,下面用matrix矩阵相乘的法则来演示。

transform: rotate(α) translate(e, f)

以上面的变换为例,这意味着先进行translate变换,再进行rotate变换。变换过程为 [ x ′ y ′ 1 ] = [ cos ⁡ α − sin ⁡ α 0 sin ⁡ α cos ⁡ α 0 0 0 1 ] [ 1 0 e 0 1 f 0 0 1 ] [ x y 1 ] \begin{bmatrix}x\prime \\ y\prime \\ 1\end{bmatrix} =\begin{bmatrix}\cos \alpha &-\sin \alpha &0\\ \sin \alpha &\cos \alpha &0\\ 0&0&1\end{bmatrix} \begin{bmatrix}1&0&e\\ 0&1&f\\ 0&0&1\end{bmatrix} \begin{bmatrix}x\\ y\\ 1\end{bmatrix} xy1=cosαsinα0sinαcosα0001100010ef1xy1把中间的matrix矩阵计算一下 [ cos ⁡ α − sin ⁡ α 0 sin ⁡ α cos ⁡ α 0 0 0 1 ] [ 1 0 e 0 1 f 0 0 1 ] = [ cos ⁡ α − sin ⁡ α e cos ⁡ α − f sin ⁡ α sin ⁡ α cos ⁡ α e sin ⁡ α + f cos ⁡ α 0 0 1 ] \begin{bmatrix}\cos \alpha &-\sin \alpha &0\\ \sin \alpha &\cos \alpha &0\\ 0&0&1\end{bmatrix} \begin{bmatrix}1&0&e\\ 0&1&f\\ 0&0&1\end{bmatrix} =\begin{bmatrix}\cos \alpha &-\sin \alpha &e\cos \alpha -f\sin \alpha \\ \sin \alpha &\cos \alpha &e\sin \alpha +f\cos \alpha \\ 0&0&1\end{bmatrix} cosαsinα0sinαcosα0001100010ef1=cosαsinα0sinαcosα0ecosαfsinαesinα+fcosα1线性方程为 { x ′ = x cos ⁡ α − y sin ⁡ α + e cos ⁡ α − f sin ⁡ α y ′ = x sin ⁡ α + y cos ⁡ α + e sin ⁡ α + f cos ⁡ α \begin{cases}x\prime =&x\cos \alpha -y\sin \alpha +e\cos \alpha -f\sin \alpha \\ y\prime =&x\sin \alpha +y\cos \alpha +e\sin \alpha +f\cos \alpha \end{cases} {x=y=xcosαysinα+ecosαfsinαxsinα+ycosα+esinα+fcosα

理解方式1:坐标原点不变

从这里可以看出,变换后的坐标相当于对原坐标做rotate变换,加上对translate增加的坐标做的rotate变换。如果我们写成 { x ′ = ( x + e ) cos ⁡ α − ( y + f ) sin ⁡ α y ′ = ( x + e ) sin ⁡ α + ( y + f ) cos ⁡ α \begin{cases}x\prime =&\left( x+e\right) \cos \alpha -\left( y+f\right) \sin \alpha \\ y\prime =&\left( x+e\right) \sin \alpha +\left( y+f\right) \cos \alpha \end{cases} {x=y=(x+e)cosα(y+f)sinα(x+e)sinα+(y+f)cosα可以看出,先做translate变换,然后将变换后的坐标整体再做rotate变换。我们的坐标系统没有变,坐标原点仍然是(0, 0),将translate所做变换后的坐标,再一起做rotate变换。对应到图形上,就是让图形先做translate变换,然后变换后的图形再做rotate变换(坐标原点为(0, 0) )。

理解方式2:坐标原点随translate改变

根据translate变换会更改坐标原点的方式,坐标原点变为 [ e cos ⁡ α − f sin ⁡ α e sin ⁡ α + f cos ⁡ α ] \begin{bmatrix}e\cos \alpha -f\sin \alpha \\ e\sin \alpha +f\cos \alpha \end{bmatrix} [ecosαfsinαesinα+fcosα],此时图形的坐标相对于新的坐标系,则线性方程变为 { x ′ = x cos ⁡ α − y sin ⁡ α y ′ = x sin ⁡ α + y cos ⁡ α \begin{cases}x\prime =&x\cos \alpha -y\sin \alpha \\ y\prime =&x\sin \alpha +y\cos \alpha \end{cases} {x=y=xcosαysinαxsinα+ycosα
此时的操作相当于,对坐标原点进行平移translate(e, f),然后再rotate(α),最后再对图形在新坐标原点上做rotate(α)。因此,translate变换如果在其他变换的右边,则其他变换要加在translate变换上再对坐标原点做变换。其实,用坐标原点跟随translate改变的理解方式比较复杂。

因此,复合变换中,translate变换如果出现在其他变换的右边,那么该复合变换不是变换之间简单的线性叠加,而是translate变换会与其他变换进行线性叠加(应用到坐标原点,从而得到新的坐标原点),再将其他变换线性叠加(直接给图形在新坐标系应用这些变换)
transform: translate(e, f) rotate(α)

作为对比,来看一下顺序相反的情况。计算得到最终的matrix矩阵为 [ cos ⁡ α − sin ⁡ α e sin ⁡ α cos ⁡ α f 0 0 1 ] \begin{bmatrix}\cos \alpha &-\sin \alpha &e\\ \sin \alpha &\cos \alpha &f\\ 0&0&1\end{bmatrix} cosαsinα0sinαcosα0ef1线性方程为 { x ′ = x cos ⁡ α − y sin ⁡ α + e y ′ = x sin ⁡ α + y cos ⁡ α + f \begin{cases}x\prime =&x\cos \alpha -y\sin \alpha +e\\ y\prime =&x\sin \alpha +y\cos \alpha +f\end{cases} {x=y=xcosαysinα+exsinα+ycosα+f可以看出,先rotate操作,再直接加上translate(e, f)坐标增量即可,不会出现上方的对translate()坐标增量也要rotate的操作。

transform: skew(θx, θy) rotate(α)与transform: rotate(α) skew(θx, θy)的对比

由于不涉及translate变换,所以我们用2*2的矩阵表示就可以了。
transform: skew(θx, θy) rotate(α)对应的matrix矩阵为 [ 1 tan ⁡ θ x tan ⁡ θ y 1 ] [ cos ⁡ α − sin ⁡ α sin ⁡ α cos ⁡ α ] = [ cos ⁡ α + sin ⁡ α tan ⁡ θ x − sin ⁡ α + cos ⁡ α tan ⁡ θ x sin ⁡ α + cos ⁡ α tan ⁡ θ y cos ⁡ α − sin ⁡ α tan ⁡ θ y ] \begin{bmatrix}1&\tan \theta_{x} \\ \tan \theta_{y} &1\end{bmatrix} \begin{bmatrix}\cos \alpha &-\sin \alpha \\ \sin \alpha &\cos \alpha \end{bmatrix} =\begin{bmatrix}\cos \alpha +\sin \alpha \tan \theta_{x} &-\sin \alpha +\cos \alpha \tan \theta_{x} \\ \sin \alpha +\cos \alpha \tan \theta_{y} &\cos \alpha -\sin \alpha \tan \theta_{y} \end{bmatrix} [1tanθytanθx1][cosαsinαsinαcosα]=[cosα+sinαtanθxsinα+cosαtanθysinα+cosαtanθxcosαsinαtanθy]
线性方程为 { x ′ = ( x cos ⁡ α − y sin ⁡ α ) + ( x sin ⁡ α + y cos ⁡ α ) tan ⁡ θ x y ′ = ( x sin ⁡ α + y cos ⁡ α ) + ( x cos ⁡ α − y sin ⁡ α ) tan ⁡ θ y \begin{cases}x\prime =&\left( x\cos \alpha -y\sin \alpha \right) +\left( x\sin \alpha +y\cos \alpha \right) \tan \theta_{x} \\ y\prime =&\left( x\sin \alpha +y\cos \alpha \right) +\left( x\cos \alpha -y\sin \alpha \right) \tan \theta_{y} \end{cases} {x=y=(xcosαysinα)+(xsinα+ycosα)tanθx(xsinα+ycosα)+(xcosαysinα)tanθy可以发现,正好是rotate后的坐标再进行skew()的过程。如果我们定义xr和yr为rotate后的坐标,可以清晰地发现这一点。rotate后的坐标如下 { x r = x cos ⁡ α − y sin ⁡ α y r = x sin ⁡ α + y cos ⁡ α \begin{cases}x_{r}=&x\cos \alpha -y\sin \alpha \\ y_{r}=&x\sin \alpha +y\cos \alpha \end{cases} {xr=yr=xcosαysinαxsinα+ycosα再进行skew的坐标如下 { x ′ = x r + y r tan ⁡ θ y y ′ = y r + x r tan ⁡ θ x \begin{cases}x\prime =&x_{r}+y_{r}\tan \theta_{y} \\ y\prime =&y_{r}+x_{r}\tan \theta x\end{cases} {x=y=xr+yrtanθyyr+xrtanθx
transform: rotate(α) skew(θx, θy)对应的matrix矩阵为 [ cos ⁡ α − sin ⁡ α sin ⁡ α cos ⁡ α ] [ 1 tan ⁡ θ x tan ⁡ θ y 1 ] = [ cos ⁡ α − sin ⁡ α tan ⁡ θ y − sin ⁡ α + cos ⁡ α tan ⁡ θ x sin ⁡ α + cos ⁡ α tan ⁡ θ y cos ⁡ α + sin ⁡ α tan ⁡ θ x ] \begin{bmatrix}\cos \alpha &-\sin \alpha \\ \sin \alpha &\cos \alpha \end{bmatrix} \begin{bmatrix}1&\tan \theta_{x} \\ \tan \theta_{y} &1\end{bmatrix} =\begin{bmatrix}\cos \alpha -\sin \alpha \tan \theta_{y} &-\sin \alpha +\cos \alpha \tan \theta_{x} \\ \sin \alpha +\cos \alpha \tan \theta_{y} &\cos \alpha +\sin \alpha \tan \theta_{x} \end{bmatrix} [cosαsinαsinαcosα][1tanθytanθx1]=[cosαsinαtanθysinα+cosαtanθysinα+cosαtanθxcosα+sinαtanθx]线性方程为 { x ′ = x r + y r tan ⁡ θ x y r = y r + x r tan ⁡ θ y \begin{cases}x\prime =&x_{r}+y_{r}\tan \theta_{x} \\ y_{r}=&y_{r}+x_{r}\tan \theta y\end{cases} {x=yr=xr+yrtanθxyr+xrtanθy

这说明,线性变换之间的顺序不会引入对坐标原点的变换,只要按照顺序依次应用变换即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值