本节书摘来异步社区《HTML5游戏编程核心技术与实战》一书中的第2章,第2.4节,作者: 向峰 责编: 杨海玲,更多章节内容可以访问云栖社区“异步社区”公众号查看。
2.4 坐标变换
HTML5游戏编程核心技术与实战
在绘制图像的过程中,经常可能需要对图像进行旋转、缩放等变形处理,canvas也提供了一系列的API帮助我们完成这些操作。
关于画布的坐标变换,canvas提供了以下常用的API,这些API的操作必须要在绘制之前调用,否则不会产生任何效果。
translate (x, y):平移,把画布的原点坐标移动到(x, y)位置,x表示将坐标原点向左移x个像素,y表示将坐标原点向下移动y个像素。正常情况下canvas的原点坐标位于左上角,那么我们可以通过translate方法移动原点的坐标,比如以下代码就把原点坐标移动到了canvas的中间位置:
context.translate(canvas.width0.5, canvas.height0.5);
scale (x, y):缩放,把画布放大。x表示水平方向放大倍数,y表示垂直方向放大倍数,如果需要缩小,将这两个参数设置为0~1之间的数就可以了,比如context.scale (0.5, 0.5)表示把图形缩小一半。
rotate (angle):把图形进行旋转。angle表示旋转的角度,旋转的中心点是原点,旋转是以顺时针方向进行,angle设置成负数就是逆时针旋转。需要注意的是angle是以弧度表示,比如要顺时针旋转90度可以使用context.rotate (Math.PI*0.5)。
transform (m11, m12, m21, m22, dx, dy):把当前的矩阵乘上如图2-20所示的矩阵,做矩阵叠加操作。
setTransform (m11, m12, m21, m22, dx, dy):设置当前的变换矩阵为图2-20所示的矩阵。
以下代码在canvas的中间位置绘制了棵小树:
代码中,首先计算出canvas的中心坐标(cx, cy),然后把canvas画布原点移动到点(cx, cy)。由于画布的原点移动到点(cx, cy)位置,那么,drawImage (img, dx, dy)表示的是把图片以(dx, dy)为左上角开始绘制。所以,如果要绘制到*,需要偏移半个宽度和高度,即使用坐标点(−w/2, −h/2)。最终效果如图2-21所示,黑线表示canvas的边框。
rotate方法描述的是图像绕原点旋转,假设要实现绕某一个图像的中心点旋转,如何实现呢?对了,我们可以先把画布的原点移动到图像的中心点,然后就可以进行旋转操作了。
以下代码绘制了在画布*,一个绕自身中心旋转并且放大了一倍的小树。
这段代码中,我们定义了一个draw方法,用于绘制图像,在绘制图像的过程中,首先保存当前的绘图状态,然后把画布移动到中心,进行旋转和放大,最后恢复画布状态。注意,如果不进行保存和恢复状态的操作,则由于使用这些变换操作都将改变当前变换矩阵的状态,从而影响下一次的变换。
定义了draw方法后,设置了一个定时器,每30毫秒改变全局的角度,形成一个旋转的动画,具体的效果如图2-22所示。
本质上,前面所介绍的rotate()、scale()、translate()等方法最终都会转换成矩阵的形式进行操作,这种对应如下所示:
translate(x, y) transform(1, 0, 0, 1, x, y)
scale(x, y) transform(sx, 0, 0, sy, 0, 0)
rotate(deg) transform(cos(deg), sin(deg), -sin(deg), cos(deg), 0, 0)
由于本质上这些变换操作都会进行矩阵和三角函数的相关运算,特别是旋转操作,所以这些变换操作将消耗更多的时间,特别是在手持设备上使用更为明显。