HTML5 Canvas – 动画
在现代 Web 开发中,动画在页面设计中扮演着越来越重要的角色。而 HTML5 Canvas 作为一个强大的绘图工具,为开发者提供了一些绘制动画的方法。
实现动画的基本原理
动画的实现原理是在一定时间间隔内,将图形的位置、大小、透明度等属性进行变化,从而实现动画效果。在 Canvas 中,这些通过变化绘制的图形实现。
具体来说,实现 Canvas 动画,主要有两种方式:
- 帧动画
- TweenJS
帧动画
帧动画是最基本的动画实现方式。原理是在一定时间内,按照一定的频率对页面进行绘制,从而达到动画的效果。
下面是一个简单实现顶部导航栏徐徐展开的帧动画示例。使用延迟函数实现动画效果。
<canvas id="canvas" width="500" height="100"></canvas>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
let i = 0;
const topNav = [
{ x: 50, y: 50 },
{ x: 80, y: 50 },
{ x: 110, y: 50 },
{ x: 140, y: 50 },
{ x: 170, y: 50 },
{ x: 200, y: 50 },
{ x: 230, y: 50 },
{ x: 260, y: 50 },
{ x: 290, y: 50 },
{ x: 320, y: 50 },
{ x: 350, y: 50 },
{ x: 380, y: 50 },
{ x: 410, y: 50 },
{ x: 440, y: 50 },
{ x: 470, y: 50 }
];
function drawTopNav(x, y, w, h) {
// 画出导航栏
ctx.fillStyle = 'purple';
for (let i = 0; i < topNav.length; i++) {
const { x, y } = topNav[i];
ctx.fillRect(x + i * 10, y, w, h);
}
}
function loop() {
requestAnimationFrame(loop);
if (i > topNav.length) {
return;
}
drawTopNav();
i += 1;
}
setTimeout(loop, 1000 / 60);
</script>
上述代码的思路是:
- 在页面上画出一个顶部导航栏
- 在循环函数
loop()
中,对导航栏进行一次更新 - 将上一步绘制的内容通过
requestAnimationFrame()
丢到浏览器的任务队列中 - 在下一个可用的浏览器渲染屏幕的时,执行循环函数
requestAnimationFrame()
相当于循环的催化剂,每次循环执行结束,都将循环函数加入到浏览器任务队列,保证动画的不停持续。
TweenJS
TweenJS 是一个简单易用的 JS 动画引擎,无需深入研究当前运动状态,可实现针对目标对象连续的缓动动画。
在使用 TweenJS 前,需要先为动画目标设置一个初始值和一个最终值,然后让 TweenJS 帮助我们计算动画过程的值。
<canvas id="canvas" width="500" height="100"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tween.js/18.6.4/tween.min.js"></script>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// 定义起始坐标和半径
let start = { x: 20, y: 20, r: 20 };
// 定义目标坐标和半径
let target = { x: 200, y: 20, r: 50 };
// 创建 tween
const tween = new TWEEN.Tween(start).to(target, 1000).start();
// 每一帧更新并重新绘制圆
function update() {
requestAnimationFrame(update);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.arc(start.x, start.y, start.r, 0, 2 * Math.PI);
ctx.fill();
TWEEN.update();
}
// 启动更新循环
requestAnimationFrame(update);
</script>
可以看到,TweenJS 通过 new TWEEN.Tween()
创建了一个动画过程,设置了起始值和目标值,并在定义的时间内完成了过渡。同时,它还提供了 TWEEN.update()
方法更新动画状态,让每一帧的过渡更加平滑。
Canvas 动画的优化
在设计 Canvas 动画的时候,我们需要考虑到性能问题。以下是一些优化指南:
- 只有在必要的时候进行绘制操作。Canvas 绘图操作较为昂贵,如果在每一帧都重新绘制,显著减慢程序运行速度。
- 避免使用像素级别的操作。尽可能地使用直线、矩形、多边形等基本图形进行绘制,而不是像素操作。每个像素的操作会让 Canvas 的机器负担大大加重。
- 使用动画图像集。如果您需要使用多个动画,您可以将它们全部绘制在一个图像集中,这样就可以减少每个动画的负担,提高绘图速度。
结论
Canvas 动画是 Web 设计和游戏开发中极为重要的一项技术。通过 Canvas 的绘图功能,可以实现众多动画效果,从而提升网页及游戏的用户体验和品质。同时,对于需要呈现大量图形的项目,Canvas 也是一种高效的设计方案。