简单理解css中transform的matrix3d()

时间:2021-03-30 12:14:29

一直想知道怎么获取transform中的各个属性值,奈何百度到的相关资料解释得过浅、错误或解释不完整,无奈只好自己摸索......。

transform小东西大智慧,其直接涉及数字图像处理的仿射变换,还好我是偏数学的IT出生,必修课程有此门课程,理解它并不费劲。总之,先把笔记做好,方便以后查看。

(注:本文涉及到矩阵运算)


直接获取transform属性的属性值会出现matrix()二维变形或matrix3d()三维变形。

matrix是矩阵的意思,其实图像的变形是把图像中每个位置的像素点乘以一个仿射矩阵,到达另外一个位置,最后把变换后的所有像素点组合起来。


matrix3d(n,n.....)的属性值是由16个值组成4乘4的仿射矩阵。

查阅资料得知其默认的仿射矩阵

简单理解css中transform的matrix3d()

4*4的单位阵

对应的matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 );

容易看出matrix3d的参数是通过拉伸,把矩阵变成一行(即:第2行开始每行放在第1行后面)


通过实验和查阅资料得到的仿射矩阵


单维平移变换(像素)

仅在X轴平移,translateX(tx)对应的仿射矩阵

简单理解css中transform的matrix3d()

对应的matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, tx, 0, 0, 1)


仅在Y轴平移,translateY(ty)对应的仿射矩阵

简单理解css中transform的matrix3d()

对应的matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, ty, 0, 1)


仅在Z轴平移,translateZ(tz)对应的仿射矩阵

简单理解css中transform的matrix3d()

对应的matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, tz, 1)

多维平移变换(像素):

简单理解css中transform的matrix3d()

对应的matrix3d(1,0,0,0,0,1,0,0,0,0,1,0,tx,ty,tz,1);

可以看出多维平移变换的仿射矩阵三个单维平移变换仿射矩阵乘积,虽然矩阵的乘积不能随便换,但此处可以互换乘积顺序。


尺度变换和平移变换相似,同理得:

多维尺度变换(像素):

简单理解css中transform的matrix3d()

对应的matrix3d(cx, 0, 0, 0, 0, cy, 0, 0, 0, 0, cz, 0, 0, 0, 0, 1 );


单维旋转变换(弧度):

(sin(θ)和cos(θ)是三角函数,不懂的同学自行百度,θ是需要旋转的弧度)

仅在X轴旋转,rotateX(θ)对应的仿射矩阵

简单理解css中transform的matrix3d()

对应的matrix3d(1,0,0,0,0,cos(θ),sin(θ),0,0,-sin(θ),cos(θ),0,0,0,0,1);


仅在Y轴旋转,rotateY(θ)对应的仿射矩阵

简单理解css中transform的matrix3d()

对应的matrix3d(cos(θ),0,-sin(θ),0,0,1,0,0,sin(θ),0,cos(θ),0,0,0,0,1);


仅在Z轴旋转,rotateZ(θ)对应的仿射矩阵

简单理解css中transform的matrix3d()

对应的matrix3d(cos(θ),sin(θ),0,0,-sin(θ),cos(θ),0,0,0,0,1,0,0,0,0,1);


多维旋转变换(弧度):

三个轴同设置时旋转的的仿射矩阵和仅旋转单一方向有一定的关系;

三轴同时旋转时按照设置顺序倒序进行仿射矩阵的生成,如这样的设置顺序:

rotateX(θ) rotateY(θ) rotateZ(θ)

则其仿射矩阵应该这样生成

简单理解css中transform的matrix3d()

三矩阵按顺序相乘,顺便不能变,矩阵乘法跟普通乘法不同。

不推荐rotateX(θ) rotateZ(θ) rotateY(θ)这样的顺序设置,火狐上会有问题。


多重3D变形

同时旋转、平移、缩放的仿射矩阵也是有规律的,通过实践得出其仿射矩阵生成规律如下:

如按照从translate、scale、rotate,坐标轴从X、Y、Z的顺序生成仿射矩阵如下:

简单理解css中transform的matrix3d()

同样矩阵按顺序相乘,不能更改顺序,否则就不是从translate、scale、rotate,坐标轴从X、Y、Z这样的顺序生成的仿射矩阵。

同样不推荐的设置顺序,如:rotateZ(90deg) translateX(10px)  scaleX(1) translateY(20px) translateZ(30px) rotateX(90deg) scaleY(2) scaleZ(3) rotateY(90deg)


理论上:如果随意设置translateX、scaleX、rotateX、translateY、scaleY、rotateY、translateZ、scaleZ、rotateZ,其仿射矩阵的生成应该是顺序设置的倒序,单维度仿射矩阵逐个相乘。并未做过实践,不保证其正确性。


至此,常用的仿射变换应该都解释完了。


实验:

给元素设置css属性:

translateX(10px) translateY(20px) translateZ(30px)  scaleX(1) scaleY(2) scaleZ(3) rotateX(90deg) rotateY(90deg) rotateZ(90deg)
先平移、后缩放、再旋转


分析:

套入上述仿射矩阵得:

简单理解css中transform的matrix3d()

matlab计算,得出结果

简单理解css中transform的matrix3d()

浏览器中JQuery获取:matrix3d(0, 0, 3, 0, 0, -2, 0, 0, 1, 0, 0, 0, 10, 20, 30, 1),结果计算正确。


换一种设置顺序:先旋转、后平移、再缩放

transform: rotateX(90deg) rotateY(90deg) rotateZ(90deg) translateX(10px) translateY(20px) translateZ(30px)  scaleX(1) scaleY(2) scaleZ(3);

matlab计算:

简单理解css中transform的matrix3d()

浏览器中JQuery获取:matrix3d(0, 0, 1, 0, 0, -2, 0, 0, 3, 0, 0, 0, 30, -20, 10, 1),结果计算正确。

值得注意的是上述两个例子,两次属性值相同顺序不同,得到的却是不同的仿射矩阵,因而,我们在设置transform属性值的时候要注意顺序


关于transform属性获取问题

如果获取的是计算后的transform,那么它返回的是一个4*4仿射。矩阵如果是多维旋转,其返回的是运算后的仿射矩阵要获取单一属性值困难的。三轴同时旋转,要从一个计算后的矩阵中分解出3个矩阵是困难的,一般都是知道其它2矩阵,才能得出第3个矩阵;如果是多重3D变形,其获取难度将更困难

举个例子:给出matrix3d(0, 0, 1, 0, 0, -2, 0, 0, 3, 0, 0, 0, 30, -20, 10, 1),能确定它是包含了什么变换吗。平移?旋转?缩放?


如果是直接获取样式表的样式,直接元素.style.transform再对它返回的字符串进行拆分可以获取到你在样式表上设置的值了。

var test = document.getElementById('div').style.transform


matrix(a,b,c,d,e,f)有位dalao做了很详细的解析,可以参考:http://www.zhangxinxu.com/wordpress/?p=2427

其中有个疑问,就是文章中解释到“xy表示转换元素的所有坐标(变量)”,理解起来挺抽象的。

参考《字图像处理》后发现,应该可以这样理解:

xy在设置偏移中心的时候是中心点的坐标;

在设置缩放、旋转、平移的时候应该是元素的像素坐标,其实就是像素点在元素中的坐标。


总结:我们在用transform的时候,所用的translate、scale、rotate,不过是修改仿射矩阵上的数值。如果单单用这些属性会被限制住,用仿射矩阵可以做一些translate、scale、rotate做不到的事情,比如我随便构造一个4*4的仿射矩阵,套用到元素中,会发生一些奇怪的事。还可参考:http://www.zhangxinxu.com/wordpress/?p=2427,一个简单的2D镜像对称例子,怎么构造出有用的仿射矩阵,我还有待研究。总之,先把笔记做好......。


文中观点若是存在疑问或不准确的,欢迎指正。感谢阅读。