Canvas学习:自定义的坐标变换

特别声明:为感谢社区广大朋友对小站的支持,自2019年10月1日至2019年11月11日开通年费VIP通道,年费价格为 ¥299.00元。如果您喜欢小站的内容,可以点击开通会员进行全站阅读。如果您对付费阅读有任何建议或想法,欢迎发送邮件至: airenliao@gmail.com!(^_^)

相对于Web坐标系统而言Canvas里的坐标系统较为复杂一些,除了默认的坐标系统之外还有坐标变换概念。在上一节中,已经了解了如何使用scale()rotate()translate()方法来变换坐标系。这三个方法提供了一种简便的手段,用于操作绘图环境对象的变换矩阵(Transformation Matrix)。默认情况下,这个变换矩阵就是单位矩阵(Identity Matrix),它并不会影响所要绘制的物体。当调用了scale()rotate()translate()方法之后,变换矩阵就会被修改,从而也会影响到所有后续的绘图操作。

在大多数情况之下,这三个方法就足够用了,不过,有些时候可能需要自己直接操作变换矩阵。比方说,如果要对所绘对象进行“错切”(Shear),那么就没有办法通过组合运用这三个方法来达成此效果。在这种情况下,就必须直接操作变换矩阵了。这一节,我们就一起来了解Canvas中的矩阵变换。

矩阵变换

Canvas的矩阵变换又称为自定义的坐标变换。Canvas的绘图环境对象(CanvasRenderingContext2D)提供了两个可以直接操作变换矩阵的方法:

  • CanvasRenderingContext2D.transform:在当前的变换矩阵之上叠加运用另外的变换效果
  • CanvasRenderingContext2D.setTransform:将当前的变换矩阵设置为默认的单位矩阵,然后在单位矩阵之上运用用户指定的变换效果

要点:多次调用transform()方法所造成的变换效果是累积的,而每次只要调用setTransform()方法,它就会将上一次的变换矩阵彻底清除。

在上一节中,我们了解到translate()rotate()scale()这三个方法都是通过操作变换矩阵来实现其功能的,也就是说,也可以直接使用transform()setTransform()方法来操作变换矩阵,实现坐标系统的平移、旋转和缩放等效果。直接使用transformsetTransform()方法操作变换矩阵有自己的优势,也有自己的劣势。

使用transform()setTransform()有两个好处:

  • 可以实现scale()rotate()translate()方法所达到的效果,比如错切效果
  • 只需调用一次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)。如果你把向量的xy分量画出来,该向量会和xy分量为边形成一个三角形:

因为两条边(xy)是已知的,如果希望知道斜边的长度,我们可以直接通过勾股定理来计算:

向量相乘

两个向量相乘是一种很奇怪的情况。普通的乘法在向量上是没有定义的,因为它在视觉上是没有意义的。但是在相乘的时候我们有两种特定情况可以选择:一个是点乘(Dot Product),记作v¯⋅k¯,另一个是叉乘(Cross Product),记作v¯×k¯

点乘

两个向量的点乘等于它们的数乘结果乘以两个向量之间夹角的余弦值。可能听起来有点费解,我们来看一下公式:

它们之间的夹角记作θ。为什么这很有用?想象如果都是单位向量,它们的长度会等于1。这样公式会有效简化成:

现在点积只定义了两个向量的夹角。你也许记得90度的余弦值是00度的余弦值是1。使用点乘可以很容易测试两个向量是否正交(Orthogonal)或平行(正交意味着两个向量互为直角)。如果你想要了解更多关于正弦或余弦函数的知识

剩余80%内容付费后可查看

如需转载,烦请注明出处:https://www.w3cplus.com/canvas/custom-of-coordinate-transformation.html

如果文章中有不对之处,烦请各位大神拍正。如果你觉得这篇文章对你有所帮助,打个赏,让我有更大的动力去创作。(^_^)。看完了?还不过瘾?点击向作者提问!

赏杯咖啡,鼓励他创作更多优质内容!
返回顶部