HTML5 - Canvas的使用样例15(动画的实现,以弹跳小球为例)
1,Canvas实现动画的原理
(1)首先设置一个定时器,反复调用绘图函数(一般每秒30~40次)。每次调用,都会重绘整个画布。完成后的效果就像动画一样,每一帧间过渡会平滑而流畅。
(2)有两种方法都可以实现重复绘制:setTimeout()和setInterval()。用哪个可以自行决定。
(3)setInterval() 能保证精确地按时重绘,当又可能因此牺牲性能(如果绘图代码执行时间比设定时间还要长,浏览器将很难跟上,随着绘图代码的连续执行,页面会出现短暂地停顿)
(4)本例使用 setTimeout(),其运行等待时间设为20毫秒(这个是典型的动画延迟时间)。
2,小球弹跳动画
(1)点击“添加小球”按钮,会在画布上添加一个小球。
(2)添加的小球会向右下做自由落体运动,碰到地板、墙壁后会反弹。同时每次反弹会受到阻力的影响,稍稍减少速度。
(3)鼠标点击任意小球,会让该小球突然加速,让它向某个方向弹开。
(4)点击“清空画布”按钮,会清除页面上的所有小球。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>hangge.com</title> <style> canvas { cursor: pointer; border: 1px solid black; } </style> <script> // 用于表示球的所有细节的Ball函数 function Ball(x, y, dx, dy, radius) { this.x = x; this.y = y; this.dx = dx; this.dy = dy; this.radius = radius; this.strokeColor = "black"; this.fillColor = "red"; } // 这个数组用于保存画布上出现的所有球 var balls = []; var canvas; var context; window.onload = function() { canvas = document.getElementById("canvas"); context = canvas.getContext("2d"); canvas.onmousedown = canvasClick; // 每0.02秒绘制一次画布 setTimeout(drawFrame, 20); }; function addBall() { // 小球半径 var radius = 20; // 创建新的ball对象 var ball = new Ball(50,50,1,1,radius); // 将其保存在balls数组中 balls.push(ball); } function clearBalls() { // 删除所有球对象 balls = []; } function drawFrame() { // 清除画布 context.clearRect(0, 0, canvas.width, canvas.height); context.beginPath(); // 循环所有的球 for(var i=0; i<balls.length; i++) { // 把每个球移动到新的位置 var ball = balls[i]; ball.x += ball.dx; ball.y += ball.dy; // 添加重力作用的效果,让球加速下落 if ((ball.y) < canvas.height) ball.dy += 0.22; // 添加摩擦力作用的效果,减慢左右移动速度 ball.dx = ball.dx * 0.998; // 如果球碰到某一边,就反弹回来 if ((ball.x + ball.radius > canvas.width) || (ball.x - ball.radius < 0)) { ball.dx = -ball.dx; } // 如果球碰到底部,反弹回来,但慢慢地减速 if ((ball.y + ball.radius > canvas.height) || (ball.y - ball.radius < 0)) { ball.dy = -ball.dy*0.96; } context.beginPath(); context.fillStyle = ball.fillColor; // 绘制球 context.arc(ball.x, ball.y, ball.radius, 0, Math.PI*2); context.lineWidth = 1; context.fill(); context.stroke(); } // 20毫秒后绘制下一帧 setTimeout(drawFrame, 20); } function canvasClick(e) { // 获取点击的坐标 var clickX = e.pageX - canvas.offsetLeft; var clickY = e.pageY - canvas.offsetTop; // 找到点中的小球 for(var i in balls) { var ball = balls[i]; if ((clickX > (ball.x-ball.radius)) && (clickX < (ball.x+ball.radius))) { if ((clickY > (ball.y-ball.radius)) && (clickY < (ball.y+ball.radius))) { // 改变点击的小球速度 ball.dx -= 2; ball.dy -= 3; return; } } } } </script> </head> <body> <canvas id="canvas" width="400" height="300"> </canvas> <div> <button onclick="addBall()">添加小球</button> <button onclick="clearBalls()">清空画布</button> </div> </body> </html>