7.4 案例实战
本节将结合案例介绍Canvas API的高级应用。
7.4.1 设计基本动画
设计动画的基本步骤如下。
第1步,清空canvas。最简单的方法是使用clearRect ()清空画布。
第2步,保存canvas状态。如果要改变canvas设置状态,如样式、变形等,需要每画一帧都重设原始状态,这时需要使用save()方法先保存canvas设置状态。
第3步,绘制动画图形(这步才是重绘动画帧)。
第4步,恢复canvas状态,如果已经保存了canvas的状态,可以使用restore()方法先恢复它,然后重绘下一帧。
有以下3种方法可以实现动画操控。
setInterval(function, delay):设定好间隔时间delay,function定期执行。
setTimeout(function, delay):设定好的时间delay,执行函数function。
requestAnimationFrame(callback):告诉浏览器希望执行动画,并请求浏览器调用指定的callback函数在下一次重绘之前更新动画。requestAnimationFrame()函数不需要指定动画关键帧间隔的时间,浏览器会自动设置。
【示例】本示例在画布中绘制一个红色方块和一个圆形球,让它们重叠显示。然后使用一个变量从图形上下文的globalCompositeOperation属性的所有参数构成的数组中,挑选一个参数显示对应的图形组合效果,通过动画循环显示所有参数的组合,效果演示如图7.18所示。
图7.18 设计图形组合动画
7.4.2 设计运动动画
在7.4.1节的示例中,我们初步掌握了基本动画的设计方法。本节会对运动有更深的了解,并学会添加一些符合物理规律的运动。
【操作步骤】
第1步,绘制小球,先建立画布。
<canvas id="canvas" width="600" height="300"></canvas>
定义一个小球对象,包含了一些相关属性,调用小球对象的draw()方法将球绘制在画布上。
这个小球实际上是一个简单的圆形,使用arc()函数绘制,效果如图7.19所示。
图7.19 设计缩放图像
第2步,添加速率。使用window.requestAnimationFrame()方法控制动画,通过递增速率矢量(ball.vx和ball.vy)移动小球。每1帧(draw()函数)先使用clear()方法清除之前帧绘制的圆形。
第3步,设计边界。若没有任何的碰撞检测,小球很快就会超出画布。因此还需要检查小球的x和y位置是否已经超出画布的尺寸,以及是否需要将速率矢量反转。把下面的检查代码添加进draw()函数中。
在浏览器中预览,移动鼠标指针到画布,可以开启动画,演示效果如图7.20所示。
图7.20 设计运动的小球
第4步,设计弹跳动画。为了让动作更真实,可以这样处理速度:
ball.vy *= .99; ball.vy += .25;
这会逐帧减少垂直方向的速度,小球最终只会在地板上弹跳。
第5步,设计长尾效果。上面使用clearRect ()方法来清除前一帧动画,如果用一个半透明的fillRect ()方法取代,就可轻松制作长尾效果,如图7.21所示。
ctx.fillStyle = 'rgba(255,255,255,0.3)'; ctx.fillRect(0,0,canvas.width,canvas.height);
图7.21 设计长尾效果
7.4.3 设计地球和月球公转动画
本例采用window.requestAnimationFrame()方法做一个小型的太阳系模拟动画,效果如图7.22所示。这个方法提供了更加平缓、更加有效率的方式执行动画,系统准备好了重绘条件,才调用绘制动画帧。一般每秒钟回调函数执行60次,也有可能会降低。
图7.22 设计地球和月球公转的动画效果
示例主要代码如下。
7.4.4 在画布上裁剪图像
在很多社交网站上能看到这样的场景:用户上传自定义头像,并对其编辑保存。多数网站实现图像编辑功能采用的是Flash技术。本例将采用HTML5技术实现此场景,HTML5具备上传图片和简单的剪贴功能,运行效果如图7.23所示。
图7.23 在画布上裁剪图像
单击“选择文件”按钮,在图库中选择图片并打开,在图像上按住鼠标左键,并向右下方拖动,出现一个蓝色虚线框。虚线区域将被剪贴到右侧目标画布中。释放鼠标左键,原画布虚线框内的局部图像就被复制到右侧目标画布。
核心代码如下,完整示例代码请参考本书源代码。