矩阵函数matrix()
和matrix3d()
是理解css3变换的两个重要途径,在大多数情况下面,我们使用css3的变换语法糖函数translate()``skew()``rotate()
以及scale()
等函数来进行元素的变换。然而,每一个变换的语法糖后面都是一个等价的矩阵。了解矩阵变换对于了解css3到底是如何变换的是非常有用的。
css3的变换根植于线性代数和几何,矩阵让我们可以创建线性变换。
首先来看看网页中的坐标系。每个文档都是一个坐标系,文档的左上角是原点,坐标(0, 0)。值沿着x轴向右增加,沿着y轴向下增加。二维坐标中是没有z轴的,在3D变换中z轴确定观察者的距离。
将变换应用于元素时,会创建局部坐标系。默认情况下,本地坐标系的原点(0, 0)位于对象的中心(50%, 50%)处。
matrix函数
css3中使用3X3来计算二维线性变化(使用4X4来计算3D变换,多出来的数字用于z轴)。语法:
1 | transform: matrix(a, b, c, d, e, f); |
矩阵表示如下图所示:
当我们应用2D变换时,浏览器将矩阵乘以一个向量:[x, y, 1]。x和y是局部坐标系内的特定的坐标。:将矩阵中每一行的行元素分别乘以向量的每一个列元素,并相加,就可以得到转换后的坐标(x’, y’),如图:
使用matrix实现translate位移
我们可以用一个简单的实例来测试下,比如矩阵[1, 0, 0, 1, 100, 50],那么如何变换?
即通过这个矩阵,将元素向x轴位移了100px,向y轴位移了50px,这也就是用matrix()
实现了transalte
方法,不过不同的是,使用矩阵的时候,这里的数字没有单位,默认是px,无法使用百分比。比如:
1 | .block{ |
使用matrix实现scale缩放
我们回看上面那个计算的图,结合上面的矩阵,发现a和d分别为1,b和c分别为0,这样计算的转换后的坐标为(1x+100, 1y+50),那么可以猜想这个a和d是不是x轴和y轴的放大缩小倍率呢?
我们构造一个新的矩阵,剔除没影响的部分:[1.5, 0, 0, 0.5, 0, 0],我们再用上面的公式计算一下可得到转换后的坐标为(2x, 0.5y)。可以猜想,x轴方向扩大了1.5倍,y轴扩大了0.5倍,也就是缩小了一半。用程序实现下:
1 | transform: matrix(1.5, 0, 0, 0.5, 0, 0) |
使用matrix实现skew扭曲
矩阵的四个参数我们知道了四个,a、d为x轴和y轴放大缩小的倍率,不进行缩放的时候都为1。e、f为x轴和y轴的位移,不进行位移的时候都为0。那我们可以尝试去掉干扰参数,然后分析这c、d这两个参数的矩阵。计算公式得出转换的坐标为(ax + cy + e1, bx + dy + f1),然后分别带入a=1, d=1, e=0, f=0
,得出转换后的坐标为(x+cy, y+bx)。好像看不出来什么。我们使用极端的情况:
- c=0, b=1,坐标为(x, y+x)
- c=1, b=0,坐标为(y+x, y)
是不是很惊奇为啥坐标(x, y+x),x和y都在正轴,为啥y有减有加?回忆下前面的内容,当使用变换transform时,会给元素创建一个本地坐标系,而坐标系的原点默认是在(center,center)的。
特别要注意本地坐标轴,扭曲的角度是相对于元素自己坐标轴的原点来讲的,刚开始弄混了,饶了好多弯路。
如图所示,x轴扭曲和y轴扭曲混合在一块不好分析,所以我单独拆开分析。这样可以得出:
1 | tanθx = b |
所以,可以得出矩阵的b和c两个数字分别控制的是元素的x轴倾斜和y轴倾斜。并且b、c的值是某个角度的tan值。所以我们在扭曲的时候只需要知道扭曲的角度就可以了。即扭曲的矩阵为:
1 | transform: matrix(0, tanθx, tanθy, 0, 0, 0); |
使用matrix实现旋转
旋转相对于上面的几个都比较复杂。矩阵形式:
1 | matrix(cosθ, sinθ, -sinθ, cosθ, 0, 0) |
可以辅助记忆:CS-SC
推导方式:http://www.cnblogs.com/ywxgod/archive/2010/08/06/1793609.html。