CSS3 矩阵变换(Matrix)


最近在实现小程序的一个关于canvas多次变换需求,由于之前不是很了解矩阵,但在我的老大的帮助下,啃下了这根硬骨头,那么canvas中的矩阵变换,用到的setTransform就是基于CSS3中的矩阵这一概念实现的,在此记录一下,日后忘记也能再翻一翻,后续也会更新关于3D Matrix的相关知识点,话不多说,开干!

一、矩阵是什么?

当你第一次听说这个名词的时候,肯定和我一样被他吓到了,其实矩阵就可以理解为我们平时看到的站队方阵,矩阵中的数字就好比每行每排的人,而矩阵间的运算就是方阵之间的队伍互冲厮杀

[       ]    [       ]  
  1,2,3        1,3,5
  4,5,6    x   7,9,2
  7,8,9        4,6,8
[       ]    [       ]

那么css中的矩阵可以理解为一个方法,matrix() 或者3D的 matrix3d(),前者是元素2D平面移动,变换或旋转、后者就是3D变换,2D变换矩阵为3x3,3D的则为4x4矩阵。

https://blog-1309278058.cos.ap-shanghai.myqcloud.com/23-07-27_01%E7%9F%A9%E9%98%B5%E6%96%B9%E9%98%B5.jpg

二、从基本属性来理解矩阵

我们常用css变换的小伙伴应该知道,transform,那么transform就有几个属性可以设置,比如缩放(scale)、旋转(rotate)、位移(translate)及斜拉(skew)

.transformSkew { transform: skew(45deg); }
.transformScale { transform:scale(0.8, 0.6); }
.transformRotate { transform:rotate(60deg); }
.transformTranslate { transform:translate(30px, 20px); }

三、transform与坐标原点

transform旋转其实是围绕着中心点旋转的,而这个中心点就是transform-origin属性的对应点,如果我们设置如下:

transform-origin: bottom left;

那么坐标中心点就位于左下角位置,那么包括缩放,旋转就都会基于左下角进行,如果想要旋转缩放基于中心点,就需要设置为:center center,表示横纵坐标 X、Y基于元素中点操作,这就是坐标原点。

当然,这个值也可以是像素,如果设置为 :60px 100px,那就会往x轴右侧偏移60像素、往y轴下方偏移100像素,仔细想想是不是就是那么回事呢。

四、矩阵应用场景

CSS3 transform 的矩阵 matrix() 方法有几个参数,具体写法:

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

当我第一次见到这些的时候还是有点懵的,六个参数,没有太大的规律,对应矩阵其实是这样的:

[ a c e ]
  b d f 
[ 0 0 1 ]

书写形式是竖着的,上面提过矩阵可以想象成的士兵方阵,要让其发生变化,就是矩阵变换,就让他们互冲,下面列一个矩阵和向量相乘的公式:

[ a c e ]    [ x ]     [ ax + cy + e ]
  b d f   x    y    =    bx + dy + f
[ 0 0 1 ]    [ 1 ]     [ 0  + 0  + 1 ]

那么应用场景就是,如果坐标系有若干个点,我需要把它们按矩阵去变换,就将点和矩阵相乘,他们的乘积就是变换后的点,如果还需要变换,可以把操作记录成矩阵,让矩阵和矩阵相乘,就是新的存档,是不是很神奇。

如果还想深入了解其原理,有个官方demo,感兴趣可以看看!

五、Matrix的计算

计算

获取当前元素的所有像素点坐标并计算

x’ = ax+cy+e

y’ = bx+dy+f

简单例子

偏移(translate)

坐标公式应该为:x’ = x + 偏移量; y‘ = y + 偏移量

套用上面的公式那么应该:a = 1; b = 0;c = 0;d = 1; e = x偏移量;f = y偏移量

matrix(1, 0, 0, 1, x偏移量, y偏移量)

缩放(scale)

x’ = xx缩放倍数 ; y’ = yy缩放倍数

a = x缩放倍数 ; b = 0; c = 0; d = y缩放倍数 ; e = 0; f = 0

matrix(x缩放倍数, 0, 0, y缩放倍数, 0, 0);

如:缩小一半, matirx(0.5,0,0,0.5,0,0);

垂直旋转(rotate)

x’ = ax + cy ; y’ = bx +dy

a = cosθ; b = sinθ; c = sinθ; d = cosθ; e = 0; f = 0;

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

如:要水平旋转30度,只需计算出cos30°和sin30°的值,作为参数a和c的值 matrix(0.866,0,0.5,1,0,0);

垂直旋转同理;

垂直旋转(rotate)

只需:水平旋转角度 = -垂直旋转角度

如:要顺时针旋转30度, matrix(0.866,0.5,-0.5,0.866,0,0);

上面的都可以用CSS3 transform提供的translate() rotate() scale() 方法实现,但有些效果不能实现。(如:镜像)
  水平镜像:(y坐标不变,x坐标变负)

所以:a=-1; b=0; c=0; d=1; e=0; f=0;简化得:
  x’ = -x;
  y’ = y

拉伸(skew)

各像素新坐标需要为

x1=x+tan(ax)*y,y1=tan(ay)*x+y,

因此等价于matrix(1,tan(ay),tan(ax),1,0,0);。例如skew(45deg);等价于matrix(1, 0, 1, 1, 0, 0);(tan(45)=1)

六、总结

我们通常使用的CSS3 transform中提供了像skew, rotate, 等简单易理解的方法,为什么还要用矩阵 Matrix3DMatrix呢。

对于一般地交互应用,transform属性默认提供的些方法是足够了,但是,一些其他的效果,如果transform属性没有提供接口方法,那你又该怎么办呢?比方说,“镜像对称效果”!

这时,就只能靠matrix矩阵了。要知道,matrix矩阵是transform变换的基础,可以应付很多高端的效果,算是一种高级应用技巧。

回见!

参考:css3-transform-matrix-矩阵

最酷炫的动画函数(matrix)详细全解


文章作者: feico
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 feico !
评论
  目录