矩阵可以用来表示图形的变换。css3定义了matrix
和matrix3d
方法,用来表示2维和3维的变换。下文将分析这两个接口的使用方法,并且用下文的思路,实现了一个简单的用js控制css3变换的jquery插件css3js ,
变换矩阵和净变换矩阵
matrix(a,b,c,d,e,f)
有六个参数,这六个参数对应到矩阵如下:
⎡⎣⎢ab0cd0ef1⎤⎦⎥
在图形学上,这种叫做齐次坐标矩阵,用齐次坐标矩阵和图形的顶点相乘,就能得到变换后的新顶点的位置。比如,图形有一个顶点(a,b),现使图形整体延x轴平移100px,平移后该顶点的位置应该是(a+100,b)。很明显,下面的矩阵运算就表示了这个过程:
⎡⎣⎢10001010001⎤⎦⎥ × ⎡⎣⎢ab1⎤⎦⎥ = ⎡⎣⎢a+100b1⎤⎦⎥
因此,知道了这个齐次坐标矩阵,就可以算出任何一点变换后的位置,所以,这个齐次坐标矩阵就是变换矩阵。
如果该点再次延y轴平移100px,平移后的新位置应该是(a+100,b+100),则整个过程可表示成:
⎡⎣⎢10001010001⎤⎦⎥ × ⎡⎣⎢10001001001⎤⎦⎥ × ⎡⎣⎢ab1⎤⎦⎥= ⎡⎣⎢1000101001001⎤⎦⎥ × ⎡⎣⎢ab1⎤⎦⎥ = ⎡⎣⎢a+100b+1001⎤⎦⎥
由此可得,图形的多次变换,可以由一个净变换矩阵表示,像上面算式中的
⎡⎣⎢1000101001001⎤⎦⎥
就是一个净变换矩阵,保存了两次变换的结果。净变换矩阵可由多个变换矩阵相乘得到。
2D变换
我们知道matrix(a,b,c,d,e,f)
有六个参数,这六个参数对应到矩阵如下:
⎡⎣⎢ab0cd0ef1⎤⎦⎥
对于常用的2D变换,图形学的相关书籍已经指出了其变换矩阵,我们直接使用就好了:
平移
⎡⎣⎢100010xy1⎤⎦⎥
所以
translate(x,y)
也可以写成`matrix(1,0,0,1,x,y)缩放
⎡⎣⎢x000y0001⎤⎦⎥
所以
scale(x,y)
也可以写成`matrix(x,0,0,y,0,0)旋转
⎡⎣⎢cos(x)sin(x)0−sin(x)cos(x)0001⎤⎦⎥
所以
rotate(x)也可以写成
matrix(cos(x),-sin(x),sin(x),cos(x),0,0)变形
⎡⎣⎢1tan(x)0tan(y)10001⎤⎦⎥所以
skew(x,y)也可以写成
matrix(1,tan(y),tan(x) ,1,0,0)
这部分可以看一下 css3js 源代码的Matrix3
的实现。
3D变换
matrix3d(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
有16个参数,这16个参数对应到矩阵如下:
⎡⎣⎢⎢⎢0123456789101112131415⎤⎦⎥⎥⎥
可以看到,这16个参数是按列排列出矩阵的。3维变换矩阵相比2维变换矩阵增加了一个维度,但是原理是相似的,也是使用齐次坐标矩阵表示变换矩阵和净变换矩阵。
在图形学上,对3维变换的变换矩阵也早有定义:
平移
⎡⎣⎢⎢⎢100001000010xyz1⎤⎦⎥⎥⎥
所以
translate(x,y,z)
也可以写成`matrix(1,0,0,0,0,1,0,0,0,0,1,0,x,y,z,1)缩放
⎡⎣⎢⎢⎢x0000y0000z00001⎤⎦⎥⎥⎥
所以
scale(x,y,z)
也可以写成`matrix(x,0,0,0,0,y,0,0,0,0,z,0,0,0,0,1)旋转
3维旋转稍微复杂,因为旋转的轴有可能不是标准的x,y,z轴了,而可能是任何一个向量。一般可用欧拉角和四元数表示旋转,而欧拉旋转由于存在“万向节死锁”问题,所以最好还是用四元数来表示。
四元数,即是一个复数:p = a i +b j +c k+d,关于四元数比较难解释,可以看中文翻译《理解四元数》。幸好,四元数变换也有变换矩阵:
⎡⎣⎢⎢⎢⎢x2∗w+cos(θ)y∗x∗w+z∗sin(θ)z∗x∗w−y∗sin(θ)0x∗y∗w−z∗sin(θ)y2∗w+cos(θ)z∗y∗w+x∗sin(θ)0x∗z∗w+y∗sin(θ)y∗z∗w−x∗sin(θ)z2∗w+cos(θ)00001⎤⎦⎥⎥⎥⎥
其中 w=1−cos(θ)
使用上面的变换矩阵可以实现在坐标原点绕任意轴的旋转,所以,变换完要做一次逆变换,将图形移回原来的位置。
这部分可以看一下 css3js 源代码的Matrix4
的实现。