深入学习CSS3的matrix属性
前言
在平时项目中绘制箭头算是很常见的一个需求,在如今的icon大行其道的时候,直接用代码写箭头样式的估计已经很少了。不过这种基础知识我们还是要好好掌握的。
1、箭头实现的老办法
老办法的实现方式如下:
老办法是使用rotate来实现上下左右的箭头的,那么今天我们不打算使用这个,而是使用CSS3更加高大上的一个属性matrix
。
2、Show Code Show code
代码demo如下:(Jsfiddle上)
3、Transform的matrix属性
想要搞懂这个matrix属性,那么不得不提到大学学过的线性代数,那么顺便我们来预习预习线性代数如何?
![](https://blogimage.5udou.cn/douBiPicture/douBi39.jpg)
丫丫,说过头了,其实不用拿本线性代数书出来,只需要回忆一下矩阵就行了。
3.1、矩阵
matrix
的中文也就是矩阵,根据wiki的解释,矩阵是一个按照行和列来排列的矩形阵列,里面的值可以是数字、符号或者表达式。比如下图:
矩阵在数学科学上有很多的应用。比如物理学家用它们来研究量子力学,通信学上用来做天线与层流的计算,而今天我们要说的是利用矩阵来做CSS上的线性变换。我们不会对线性代数有太深的挖掘,不过还是需要你回顾一下以前线性代数的一些矩阵基础。而这里我们需要知道的基础便是矩阵乘法
。
3.1.1、矩阵乘法
那么矩阵乘法的运算规则是什么呢? 来来,再次引用维基百科中专业的定义:
矩阵相乘最重要的方法是一般矩阵乘积。它只有在第一个矩阵的列数(column)和第二个矩阵的行数(row)相同时才有定义。一般单指矩阵乘积时,指的便是一般矩阵乘积。若A为 m X n矩阵,B为 n X p矩阵,则他们的乘积AB(有时记做A · B)会是一个 m X p矩阵。其乘积矩阵的元素如下面式子得出:
以向量和向量[1 2 3]
的乘法为例子,其结果应为:
3.2、Transform(以2D为例子)的四大属性
我们平时一直使用translate
,scale
,rotate
,skewX/Y
来实现各种动画变换:平移、缩放、旋转、倾斜。我们大致回忆一下这四个属性的用法:
- translate(offsetX, offsetY): 平移,可以在X轴或者Y轴上平移,平移前后的坐标变换关系是(newX, newY) = (oldX + offsetX, oldY+offsetY), 其期望的矩阵应该是这种类型的:
- scale(scaleX, scaleY): 缩放,可以在X轴或者Y轴上缩放,缩放前后的坐标变换关系是 (newX, newY) = (oldX * scaleX, oldY * scaleY),其期望的矩阵应该是这种类型:
- rotate(): 旋转,围绕着transform-origin配置的中心点旋转,旋转前后的坐标变换关系是(newX, newY) = (oldX * - oldY * , oldX * + oldY * ),其期望的矩阵应该是这种类型的:
旋转的这个公式示意图会在后续的更新中添加上,我将使用SVG来描述这种转换关系,让大家知其所以然
- skew(, ): 倾斜,围绕着transform-origin配置的中心点倾斜,倾斜前后的坐标变换关系是(newX, newY) = (oldX * - oldY * , oldX * + oldY * ),其期望的矩阵应该是这种类型的:
3.3、matrix上场
前面我们在说明transform的四大属性的时候,一直在强调可以使用相关的矩阵来表示,从数学上来说,所有的变化都可以使用下列3*3
的变换矩阵来表示:
因此之前提到的相关矩阵都可以算成是该通用矩阵的子集,但机智的童鞋们肯定会问到:为什么刚才明明使用2 X 3的矩阵就可以计算出来,为什么通用矩阵就变成了3 X 3的呢?这不是多此一举呢?如果是3 X 3的矩阵,为什么第三行就必须是[ 0 0 1]呢?
这个问题我们先不马上说原因,大家往后继续阅读文章自然会找到答案
看到该通用矩阵后我们知道只用了6个值,对应到CSS3的matrix属性便是:transform: matrix(a, b, c, d, e, f)
。然后再结合上一小节的各种变换公式,我们是不是可以总结出什么?
如下表:
通过这张表你可以清晰地看出四大属性与matrix属性之间的关联,那么问题来了,如果我是多种变换组合在一起呢?那么这个时候就可以使用矩阵连续相乘得到结果,于是乎,在这个点上我们就可以回答刚才的问题了,因为根据矩阵的乘法计算规则,两个矩阵相乘必须满足只有在第一个矩阵的列数(column)和第二个矩阵的行数(row)相同时才有定义,所以你不可能将一个2 X 3的矩阵乘以一个2 X 3的矩阵,因此我们需要扩展成3 X 3的矩阵,然后为了保证第三行的数值不会影响到我们的结果,其值只能是[0 0 1]
举个栗子:
1.demo{ 2 transform-origin: 0px 0px; 3 transform: rotate(45deg) translate(100px, 0) scale(2); 4}
那么其矩阵的表达式应该是:
然后再乘以对应的点,我们只需要提供上述矩阵相乘得到的结果赋值给matrix属性,其他的点积计算交由浏览器来执行,所以其等效的配置是:
1.demo{ 2 transform-origin: 0px 0px; 3 transform: matrix(1.41421, 1.41421, -1.41421, 1.41421, 70.7107, 70.7107); 4}
这里写了一个小demo,可以方便地进行二者转换,狠狠戳demo。
3.4、matrix3D
学习了2D的矩阵变换,那么3D的变换也就不在话下了,其语法是:
matrix3d(a1, b1, c1, d1, a2, b2, c2, d2, a3, b3, c3, d3, a4, b4, c4, d4)
这里就不再细说3D的矩阵变换了。
4、写在最后
如此一来,想必对CSS3的整个transfrom属性有了质的理解了吧?通过写这篇文章,我自己都学到很多,不仅仅是专业知识,还有其他一些基本技能,比如:
- 为了让我的博客支持数学公式,于是我就在我的markdown中嵌入了
kaTex
的插件,手动改了marked.js
的源码, - 为了写出数学公式,还需要学习
LaTex
的语法(后续写一篇介绍LaTex
语法的文章,敬请期待) - 为了展示旋转的原理,使用
SVG
画图,重新温习了一下几何代数。
因此一篇文章的完成会给你带来的知识会是很多很多,在此鼓励童鞋们多多总结,深入挖掘,共同学习。
参考
- https://www.w3.org/TR/SVG/coords.html#TransformMatrixDefined
- The MathML markup used to display the mathematical equations in this article were rendered by MathJax, an excellent open-source JavaScript library
- https://www.w3.org/TR/css-transforms-1/#mathematical-description
- http://www.useragentman.com/blog/2011/01/07/css3-matrix-transform-for-the-mathematically-challenged/
- https://zh.wikipedia.org/wiki/%E7%9F%A9%E9%99%A3%E4%B9%98%E6%B3%95
公众号关注一波~
![微信公众号](https://blogimage.5udou.cn/homePage/%E5%85%AC%E4%BC%97%E5%8F%B7-%E7%99%BD%E8%89%B2%E7%89%88.png?x-oss-process=style/addWaterMarkBottom)
网站源码:linxiaowu66 · 豆米的博客
Follow:linxiaowu66 · Github
关于评论和留言
如果对本文 深入学习CSS3的matrix属性 的内容有疑问,请在下面的评论系统中留言,谢谢。