![HTML5 APP开发从入门到精通(微课精编版)](https://wfqqreader-1252317822.image.myqcloud.com/cover/420/31794420/b_31794420.jpg)
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所示。
![](https://epubservercos.yuewen.com/43C118/17214367505511406/epubprivate/OEBPS/Images/Figure-P128_41131.jpg?sign=1738903148-fRVD3pzh2iWGL5Asq1riF9kJCyTym4mp-0-e157b826a541ceba91d146f2332de3c0)
![](https://epubservercos.yuewen.com/43C118/17214367505511406/epubprivate/OEBPS/Images/Figure-P129_14006.jpg?sign=1738903148-E8QQKGrSv8MvRh3W0WwRjrIfJDr7lu1z-0-7d940357f0e9020896a808574353fb0b)
图7.18 设计图形组合动画
7.4.2 设计运动动画
在7.4.1节的示例中,我们初步掌握了基本动画的设计方法。本节会对运动有更深的了解,并学会添加一些符合物理规律的运动。
【操作步骤】
第1步,绘制小球,先建立画布。
<canvas id="canvas" width="600" height="300"></canvas>
定义一个小球对象,包含了一些相关属性,调用小球对象的draw()方法将球绘制在画布上。
![](https://epubservercos.yuewen.com/43C118/17214367505511406/epubprivate/OEBPS/Images/Figure-P129_41133.jpg?sign=1738903148-jv7ykn7DjhPlb1NmKBVULuLEdr3XHA1Z-0-65197cc4c4b45c85ad963e3744b0139b)
这个小球实际上是一个简单的圆形,使用arc()函数绘制,效果如图7.19所示。
![](https://epubservercos.yuewen.com/43C118/17214367505511406/epubprivate/OEBPS/Images/Figure-P130_14084.jpg?sign=1738903148-Q6qBVyvuawhRFl8hbfm1EEHmDc3prGFm-0-4552d32d394b83873823f6503b9b6633)
图7.19 设计缩放图像
第2步,添加速率。使用window.requestAnimationFrame()方法控制动画,通过递增速率矢量(ball.vx和ball.vy)移动小球。每1帧(draw()函数)先使用clear()方法清除之前帧绘制的圆形。
![](https://epubservercos.yuewen.com/43C118/17214367505511406/epubprivate/OEBPS/Images/Figure-P130_14083.jpg?sign=1738903148-wPziLMnv4agU7oAnA7WZ5m2F5dO3wtO7-0-aa384fa4a3209f17547023e1f47b79f7)
第3步,设计边界。若没有任何的碰撞检测,小球很快就会超出画布。因此还需要检查小球的x和y位置是否已经超出画布的尺寸,以及是否需要将速率矢量反转。把下面的检查代码添加进draw()函数中。
![](https://epubservercos.yuewen.com/43C118/17214367505511406/epubprivate/OEBPS/Images/Figure-P130_41140.jpg?sign=1738903148-qZAWHGUemTAN2yYdyuCW4igh1geRwqFL-0-4662d9a77308b0e1bf8d54f722dc9bea)
在浏览器中预览,移动鼠标指针到画布,可以开启动画,演示效果如图7.20所示。
![](https://epubservercos.yuewen.com/43C118/17214367505511406/epubprivate/OEBPS/Images/Figure-P131_14140.jpg?sign=1738903148-dAgCK98B8GC1HgRPrrhFLRkQR2a90jtR-0-04004aa32bd8e8d15226016f6a1ff13f)
图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);
![](https://epubservercos.yuewen.com/43C118/17214367505511406/epubprivate/OEBPS/Images/Figure-P131_14141.jpg?sign=1738903148-DuT8qImUMIjt24GufpFodgfzH8DP3uuR-0-7748d8df2475a923cdca923466beb484)
图7.21 设计长尾效果
7.4.3 设计地球和月球公转动画
本例采用window.requestAnimationFrame()方法做一个小型的太阳系模拟动画,效果如图7.22所示。这个方法提供了更加平缓、更加有效率的方式执行动画,系统准备好了重绘条件,才调用绘制动画帧。一般每秒钟回调函数执行60次,也有可能会降低。
![](https://epubservercos.yuewen.com/43C118/17214367505511406/epubprivate/OEBPS/Images/Figure-P131_14146.jpg?sign=1738903148-jmBFyAyouRD6aCpK4LWybgk6WNVYwWPL-0-5f3205f972e6e68bf98181eb66010a51)
图7.22 设计地球和月球公转的动画效果
示例主要代码如下。
![](https://epubservercos.yuewen.com/43C118/17214367505511406/epubprivate/OEBPS/Images/Figure-P132_14224.jpg?sign=1738903148-3Emg4lueUQoAp6L3CcEFmlzRwYdm63Aq-0-28f2fc1087d39c8dbc47a54e65e18053)
7.4.4 在画布上裁剪图像
在很多社交网站上能看到这样的场景:用户上传自定义头像,并对其编辑保存。多数网站实现图像编辑功能采用的是Flash技术。本例将采用HTML5技术实现此场景,HTML5具备上传图片和简单的剪贴功能,运行效果如图7.23所示。
![](https://epubservercos.yuewen.com/43C118/17214367505511406/epubprivate/OEBPS/Images/Figure-P132_14227.jpg?sign=1738903148-IXRqVieyLWdSTYz1xru9Ge9oNUtITXLo-0-3af8c9719d3b5139fb52cbc9305621a3)
图7.23 在画布上裁剪图像
单击“选择文件”按钮,在图库中选择图片并打开,在图像上按住鼠标左键,并向右下方拖动,出现一个蓝色虚线框。虚线区域将被剪贴到右侧目标画布中。释放鼠标左键,原画布虚线框内的局部图像就被复制到右侧目标画布。
核心代码如下,完整示例代码请参考本书源代码。
![](https://epubservercos.yuewen.com/43C118/17214367505511406/epubprivate/OEBPS/Images/Figure-P133_41151.jpg?sign=1738903148-nJzmpqIRVJ5LlG0Tmr0JoJBNNwG4K1zv-0-f3848f055ceacaf9f57278acf20a4cb0)
![](https://epubservercos.yuewen.com/43C118/17214367505511406/epubprivate/OEBPS/Images/Figure-P134_14436.jpg?sign=1738903148-bkA9YuirJ5MwIkNGXbpue9l6aTzsth4V-0-a480acf2bcbf70c48612a24bd448eb06)