【学习记录10】学习CSS3 transform中的Matrix(矩阵)

先说点废话,写这篇文章是因为在学习一个vue网课的时候用到了transform动画中的matrix,就去学习了一下,此文章是在大佬张鑫旭的博客中学习以后,我又记录巩固了一下大部分内容都是来着大佬博客中。费话不多说,步入正题!

一、什么是矩阵

        在数学中,矩阵(Matrix)是一个按照长方阵列排列的复数实数集合 [1]  ,最早来自于方程组系数常数所构成的方阵。这一概念由19世纪英国数学家凯利首先提出。矩阵是高等代数学中的常见工具,也常见于统计分析等应用数学学科中。。。。。。

当看到上面“Matrix(矩阵)”的时候,是不是会心生畏惧(即使你已经学过),正常现象。实际上,这玩意确实有点复杂。[捂脸]

简单的理解

矩阵可以理解为方阵,只不过,平时方阵里面站的是人,矩阵中是数值:
方阵 矩阵示意 张鑫旭-鑫空间-鑫生活

而所谓矩阵的计算,就是两个方阵的人(可以想象成古代的方阵士兵)相互冲杀。

CSS3中的矩阵
        CSS3中的矩阵指的是一个方法,书写为matrix()matrix3d(),前者是元素2D平面的移动变换(transform),后者则是3D变换。2D变换矩阵为3*3, 如上面矩阵示意图;3D变换则是4*4的矩阵。

        是不是有些迷糊?恩,我也觉得上面讲述有些不合时宜。那好,我们先看看其他东西,层层渐进——transform属性。

我们在css中常用的transform中有这么几个属性方法:

.trans_skew { transform: skew(35deg); }
.trans_scale { transform:scale(1, 0.5); }
.trans_rotate { transform:rotate(45deg); }
.trans_translate { transform:translate(10px, 20px); }

         斜拉(skew),缩放(scale),旋转(rotate)以及位移(translate)。

         那你有没有想过,为什么transform: rotate(45deg);会让元素旋转45°, 其后面运作的机理是什么呢?

        无论是旋转还是拉伸什么的,本质上都是应用的matrix()方法实现的(修改matrix()方法固定几个值),只是类似于transform: rotate这种表现形式,我们更容易理解,记忆与上手。其实等同于用matrix()来实现的。

换句话说,理解transformmatrix()矩阵方法有利于透彻理解CSS3的transform属性。

虽然题目写的是“transform中的matrix”,实际上,在CSS3以及HTML5的世界里,这玩意还是涉猎蛮广的,如SVG以及canvas。

二、transform与坐标系统

        用过transform旋转的人可以发现了,其默认是绕着中心点旋转的,而这个中心点就是transform-origin属性对应的点,也是所有矩阵计算的一个重要依据点(下图参考自dev.opera.com)。
transform坐标系统

当我们通过transform-origin属性进行设置的时候,矩阵相关计算也随之发生改变。反应到实际图形效果上就是,旋转拉伸的中心点变了!

举例来说,如果偶们设置:

-webkit-transform-origin: bottom left;

则,坐标中心点就是左下角位置。于是动画(例如图片收缩)就是基于图片的左下角这一点了。

再举个稍微难理解的例子,我们如果这样设置:

transform-origin: 50px 70px;

则,中心点位置有中间移到了距离左侧50像素,顶部70像素的地方(参见下图),而此时的(30, 30)的坐标为白点所示的位置(这个位置后面会用到)。
中心坐标数值偏移的理解 张鑫旭-鑫空间-鑫生活

三、准备好了没?重头戏来了,下面正式进入学习矩阵

CSS3 transformmatrix()方法写法如下:

transform: matrix(a,b,c,d,e,f);

吓住了吧,哈哈...,这多参数,一个巴掌都数不过来。

实际上,这6参数,对应的矩阵就是:
矩阵参数与矩阵对应关系 张鑫旭-鑫空间-鑫生活

注意书写方向是竖着的

上面提过,矩阵可以想象成古代的士兵方阵,要让其发生变化,只有与另外一个士兵阵火拼就可以了,即使这是个小阵。

反应在这里就是如下转换公式:
CSS3中矩阵位置计算公式 张鑫旭-鑫空间-鑫生活

其中,xy表示转换元素的所有坐标(变量)了。那后面的ax+cy+e怎么来的呢?

// 大学时候线性代数知识,懂的人这里可以直接跳过(我也不懂也是从这开始学习的 [捂嘴笑] )

3*3矩阵每一行的第1个值与后面1*3的第1个值相乘,第2个值与第2个相乘,第3个与第3个,然后相加.

ax+cy+e的意义是什么?
ax+cy+e为变换后的水平坐标,bx+dy+f表示变换后的垂直位置。

假设矩阵参数如下:

transform: matrix(1, 0, 0, 1, 30, 30); /* a=1, b=0, c=0, d=1, e=30, f=30 */

现在,我们根据这个矩阵偏移元素的中心点,假设是(0, 0),即x=0y=0

于是,变换后的x坐标就是ax+cy+e = 1*0+0*0+30 =30y坐标就是bx+dy+f = 0*0+1*0+30 =30

于是,中心点坐标从(0, 0)变成了→(30, 30)。对照上面有个(30, 30)的白点图,好好想象下,原来(0,0)的位置,移到了白点的(30, 30)处,怎么样,是不是往右下方同时偏移了30像素哈!!

实际上transform: matrix(1, 0, 0, 1, 30, 30);就等同于transform: translate(30px, 30px);. 注意:translaterotate等方法都是需要单位的,而matrix方法e, f参数的单位可以省略。

1、偏移translate()

聪明的你可能以及意识到了,matrix表现偏移就是:

transform: matrix(与我无关, 哪位, 怎么不去高考, 打麻将去吧, 水平偏移距离, 垂直偏移距离);

transform: matrix(0, 0, 0, 0, 10, 10);

等同于

transform: translate(10px, 10px)

你只要关心后面两个参数就可以了,至于前面4个参数,是牛是马,是男是女都没有关系的。

2、缩放scale()

上面的偏移只要关心最后两个参数,这个缩放也是只要关心两个参数。哪两个呢?

transform: matrix(1, 0, 0, 1, 30, 30);

发现没,matrix(1, 0, 0, 1, 30, 30);的元素比例与原来一样,1:1, 而这几个参数中,有两个1, 啊哈哈!没错,这两个1就是缩放相关的参数。

其中,第一个缩放x轴,第二个缩放y轴。

用公式就很明白了,假设比例是s,则有matrix(s, 0, 0, s, 0, 0);,于是,套用公式,就有:
x' = ax+cy+e = s*x+0*y+0 = s*x;
y' = bx+dy+f = 0*x+s*y+0 = s*y;

别看上面一堆挺复杂的其实结果就是如下:

transform: matrix(0.8, 0, 0, 0.7, 0, 0);

等同于

transform: scale(0.8, 0.7);

3、旋转rotate()

旋转相比前面两个要更高级些,要用到(可能勾起学生时代阴影的)三角函数。跟着大佬(当然不是我啦)->(张鑫旭大佬)学习一下,对于我这个渣渣来说早就忘记了...

方法以及参数使用如下(假设角度为θ):

matrix(cosθ,sinθ,-sinθ,cosθ,0,0)

结合矩阵公式,就有:

x' = x*cosθ-y*sinθ+0 = x*cosθ-y*sinθ
y' = x*sinθ+y*cosθ+0 = x*sinθ+y*cosθ

不过,说句老实话,就旋转而言,rotate(θdeg)这种书写形式要比matrix简单多了,首先记忆简单,其次,无需计算。例如,旋转30°,前者直接:

transform:rotate(30deg);

而使用matrix表示则还要计算cossin值:

transform: matrix(0.866025,0.500000,-0.500000,0.866025,0,0);

总结一下就是旋转30度,rotate(30deg)

transform: rotate(30deg);

等同于

transform: matrix(0.866025,0.500000,-0.500000,0.866025,0,0);

上面的数据是利用公式

matrix(cos30°,sin30°,-sin30°,cos30°,0,0)

得出结果

matrix(0.866025,0.500000,-0.500000,0.866025,0,0);

4、拉伸skew()

拉伸也用到了三角函数,不过是tanθ,而且,其至于b, c两个参数相关,书写如下(注意y轴倾斜角度在前):

matrix(1,tan(θy),tan(θx),1,0,0)

套用矩阵公式计算结果为:

x' = x+y*tan(θx)+0 = x+y*tan(θx) 
y' = x*tan(θy)+y+0 = x*tan(θy)+y

对应于skew(θx + "deg",θy+ "deg")这种写法。

其中,θx表示x轴倾斜的角度,θy表示y轴,两者并无关联。

总结一下拉伸就是如下:

transform: skew(40deg, 30deg);

等同于

transform: matrix(1, 0.577350, -0.839099, 1, 0, 0);

上面的数据是利用公式

matrix(1, tan30°, tan40°, 1, 0, 0)

得出结果

matrix(1, 0.577350, -0.839099, 1, 0, 0);

根据如上的结论推断,最终的结果可以总结为如下:

transform: matrix(1, 0, 0, 1, 30, 30);
// matrix的参数可以理解为如下:
transform: matrix(x方向的缩放, y方向的倾斜, x方向的倾斜, y方向的缩放, x方向的偏移, y方向的便宜);

以上是我学习的结果,如果有错误还有大佬们指出问题和不对的地方,感谢大家的阅读。

再来一张我自己手写的学习记录(哈哈哈) 

 

最后奉上张鑫旭大佬的原文地址

猜你喜欢

转载自blog.csdn.net/wenhui6/article/details/118525526