相对于Web坐标系统而言Canvas里的坐标系统较为复杂一些,除了默认的坐标系统之外还有坐标变换概念。在上一节中,已经了解了如何使用 scale() 、 rotate() 和 translate() 方法来变换坐标系。这三个方法提供了一种简便的手段,用于操作绘图环境对象的变换矩阵(Transformation Matrix)。默认情况下,这个变换矩阵就是 单位矩阵 (Identity Matrix),它并不会影响所要绘制的物体。当调用了 scale() 、 rotate() 或 translate() 方法之后,变换矩阵就会被修改,从而也会影响到所有后续的绘图操作。
在大多数情况之下,这三个方法就足够用了,不过,有些时候可能需要自己直接操作变换矩阵。比方说,如果要对所绘对象进行“ 错切 ”(Shear),那么就没有办法通过组合运用这三个方法来达成此效果。在这种情况下,就必须直接操作变换矩阵了。这一节,我们就一起来了解Canvas中的矩阵变换。
矩阵变换Canvas的矩阵变换又称为 自定义的坐标变换 。Canvas的绘图环境对象( CanvasRenderingContext2D )提供了两个可以直接操作变换矩阵的方法:
要点:多次调用 transform() 方法所造成的变换效果是累积的,而每次只要调用 setTransform() 方法,它就会将上一次的变换矩阵彻底清除。
在上一节中,我们了解到 translate() 、 rotate() 和 scale() 这三个方法都是通过操作变换矩阵来实现其功能的,也就是说,也可以直接使用 transform() 和 setTransform() 方法来操作变换矩阵,实现坐标系统的平移、旋转和缩放等效果。直接使用 transform 和 setTransform() 方法操作变换矩阵有自己的优势,也有自己的劣势。
使用 transform() 和 setTransform() 有两个好处:
使用 transform() 和 setTransform() 方法的主要缺点则是,这两个方法不像 scale() 、 rotate() 和 translate() 方法那样直观。
上面的内容简单的提到 transform() 和 setTransform() 方法是操作变换矩阵,那么要彻底的理解这两个方法,就得对矩阵有所了解。为了帮助大家更好的理解这两个方法,先来了解一下矩阵相关的知识。如果你对矩阵比较了解,可以忽略这些内容,直接跳到后面你想阅读的部分。
矩阵基础知识矩阵 是一种非常有用的数学工具,尽管听起来可能有些吓人,不过一旦你理解了它们后,它们会变得非常有用。在讨论矩阵的过程中,我们需要使用到一些数学知识。对于一些愿意多了解这些知识的同学,我会附加一些资源给你们阅读。
在深入了解矩阵之前我们有必要先了解一些相关的概念。这一节的目标就是让大家拥有将来需要的最基础的数学背景知识。如果你发现这节十分困难,尽量尝试去理解它们,当你以后需要它们的时候回过头来复习这些概念。
向量向量最基本的定义就是一个方向。或者更正式的说,向量有一个方向(Direction)和大小(Magnitude,也称之为长度)。可以把向量想像成一个藏宝图上的指示:“向左走十步,向北走三步,然后向右走五步”;“左”就是方向,“十步”就是向量的长度。那么这个藏宝图的指示一共有三个向量。向量可以在任意维度(Dimension)上,但是我们通常只使用 2~4 维。如果一个向量有两个维度,它表示一个平面的方向(想像一下2D的图像),当它有三个维度的时候,它可以表达一个3D世界的方向。
下图展示了三个向量,每个向量在2D图像中都用一个箭头 (x,y) 表示。我们在2D图片中展示这些向量,因为这样子会更直观一点。由于向量表示的是方向,起始于何处并不会改变它的值。
数学家喜欢在字母上面加一横表示向量,比如说在 v 的上面加 - 。当用在公式中时它们通常是这样的:
注:把2D向量当做 z 坐标轴为 0 的3D向量。
由于向量是一个方向,所以有些时候会很难形象地将它们用位置表示出来。为了让其更为直观,通常设定这个方向的原点为 (0,0,0) (在2D世界中,这个原点就是 (0,0) ),然后指向一个方向,对应一个点,使其变为 位置向量(Position Vector) 。比如上图中位置向量 (3,2) 在图像中的起点会是 (0,0) ,并会指向 (3,2) 。
向量与标量运算标量(Scalar)只是一个数字(或者说是仅有一个分量的向量)。当把一个向量加、减、乘或除一个标量,我们可以简单的把向量的每个分量分别进行该运算。对于加法来说会像这样:
其中的 + 可以是 + , - , · 或 ÷ ,其中 · 是乘号。 注意, - 和 ÷ 运算时不能颠倒(标量 -/÷向量),它为颠倒的运算是没有定义的 。
向量取反对一个向量取反(Negate)会将其方向逆转。一个向东北的向量取反后就指向西南方向了。我们在一个向量的每个分量前加负号就可以实现取反了(或者说用 -1 数乘该向量):
向量加减
向量的加法可以被定义为是分量的(Component-wise)相加,即将一个向量中的每一个分量加上另一个向量的对应分量:
向量 v = (4, 2) 和 k = (1, 2) 可以直观地表示为:
就像普通数字的加减一样,向量的减法等于加上第二个向量的相反向量:
两个向量的相减会得到这两个向量指向位置的差。这在我们想要获取两点的差会非常有用。
长度
我们使用 勾股定理 (Pythagoras Theorem)来获取向量的长度(Length)/大小(Magnitude)。如果你把向量的 x 与 y 分量画出来,该向量会和 x 与 y 分量为边形成一个 三角形 :
因为两条边( x 和 y )是已知的,如果希望知道斜边 v¯ 的长度,我们可以直接通过勾股定理来计算:
向量相乘