多图预警,数学不好可直接跳至文末小结。
需求背景
从一个游戏需求说起:
- 技术选型:canvas
上图所展示的游戏场景,“可乐瓶”里有多个“气泡”,需要设置不同的动画效果,且涉及 deviceOrientation 的交互,需要有大量计算改变元素状态。从性能方面考虑,canvas 是不二的选择。 - 技术点:canvas 绘制图像
通过对游戏场景的进一步分析,可见场景中的“气泡”元素形状都是相同的,且不规则,通过 canvas 直接绘制形状实现成本较高,因此需要在 canvas 上绘制图像。 - 技术点:canvas 图像旋转与翻转
虽然“气泡”元素是相同的,可以使用相同的图像,但图像需要多个角度/多个方向展示,因此需要对图像进行相应的旋转与翻转(镜像),这也是本文所要介绍的重点。
后文代码以下图左侧绿框的“气泡”为示例,右侧展示了场景中用到的两个图像:
认识 canvas 坐标系
canvas 上图像的旋转和翻转,常见的做法是将 canvas 坐标系统进行变换。因此,我们需要先认识 canvas 坐标系统:
由上图可得,canvas 2D 环境中坐标系统和 Web 的坐标系统是一致的,有以下几个特点:
- 坐标原点 (0,0) 在左上角
- X坐标向右方增长
- Y坐标向下方延伸
回到上述需求中,我们获取 canvas 对象并设置相应的宽高:
1 |
// 获取 canvas 对象 |
此时,canvas 的坐标系统如下图所示:
在 canvas 上绘制图像
在 canvas 上绘制图像,可以使用 drawImage()
方法,语法如下(详细用法参见 MDN):
1 |
void ctx.drawImage(image, dx, dy); |
需要注意的是,图像必须加载完毕,才能绘制到 canvas 上,否则会出现空白:
1 |
var img = new Image() |
此时,便可以 canvas 上看到一个未旋转/翻转的“气泡”图像,如下图所示:
canvas 坐标变换
接下来,我们再来了解 canvas 坐标的变换。上述需求仅涉及 2D 绘制上下文,因此仅介绍 2D 绘制上下文支持的各种变换:
平移 translate:
1
ctx.translate(x, y)
translate() 方法接受两个参数。x 是左右偏移量,y 是上下偏移量。
旋转 rotate:
1
ctx.rotate(angle)
rotate() 方法只接受一个参数。旋转的角度 angle,它是顺时针方向的,以弧