动画原理——边界
书籍名称:HTML5-Animation-with-JavaScript
书籍源码:https://github.com/lamberta/html5-animation
1.判断球体是否出界程序
一.画板的边界就是整个画板,也就是画板的形成的矩形。
var left = 0, top = 0, right = canvas.width, bottom = canvas.height;
二.判断一个球体是否跑出边界,要考虑球的半径,位置,和边界。用代码表示,if中的条件,分别对应右左上下的出界条件。
if (ball.x – ball.radius > canvas.width || ball.x + ball.radius < 0 || ball.y – ball.radius > canvas.height || ball.y + ball.radius < 0) { balls.splice(balls.indexOf(ball), 1); }
三.判断球体出界程序
01-removal.html
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!doctype html> <html> <head> <meta charset="utf-8"> <title>Removal</title> <link rel="stylesheet" href="../include/style.css"> </head> <body> <header> Example from <a href="http://amzn.com/1430236655?tag=html5anim-20"><em>Foundation HTML5 Animation with JavaScript</em></a> </header> <canvas id="canvas" width="400" height="400"></canvas> <textarea id="log"></textarea> <script src="../include/utils.js"></script> <script src="./classes/ball.js"></script> <script> window.onload = function () { var canvas = document.getElementById('canvas'), context = canvas.getContext('2d'), log = document.getElementById('log'), balls = [], numBalls = 10; for (var ball, i = 0; i < numBalls; i++) { ball = new Ball(20); ball.id = "ball" + i; ball.x = Math.random() * canvas.width; ball.y = Math.random() * canvas.height; ball.vx = Math.random() * 2 - 1; ball.vy = Math.random() * 2 - 1; balls.push(ball); } function draw (ball, pos) { ball.x += ball.vx; ball.y += ball.vy; if (ball.x - ball.radius > canvas.width || ball.x + ball.radius < 0 || ball.y - ball.radius > canvas.height || ball.y + ball.radius < 0) { balls.splice(pos, 1); //remove ball from array if (balls.length > 0) { log.value = "Removed " + ball.id; } else { log.value = "All gone!"; } } ball.draw(context); } (function drawFrame () { window.requestAnimationFrame(drawFrame, canvas); context.clearRect(0, 0, canvas.width, canvas.height); var i = balls.length; while (i--) { draw(balls[i], i); } }()); }; </script> </body> </html>
2.重新生成已经出界的对象
02-fountain.html
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!doctype html> <html> <head> <meta charset="utf-8"> <title>Fountain</title> <link rel="stylesheet" href="../include/style.css"> </head> <body> <header> Example from <a href="http://amzn.com/1430236655?tag=html5anim-20"><em>Foundation HTML5 Animation with JavaScript</em></a> </header> <canvas id="canvas" width="400" height="400"></canvas> <script src="../include/utils.js"></script> <script src="./classes/ball.js"></script> <script> window.onload = function () { var canvas = document.getElementById('canvas'), context = canvas.getContext('2d'), balls = [], numBalls = 80, gravity = 0.5; for (var ball, i = 0; i < numBalls; i++) { ball = new Ball(2, Math.random() * 0xffffff); ball.x = canvas.width / 2; ball.y = canvas.height; ball.vx = Math.random() * 2 - 1; ball.vy = Math.random() * -10 - 10; balls.push(ball); } function draw (ball) { ball.vy += gravity; ball.x += ball.vx; ball.y += ball.vy; if (ball.x - ball.radius > canvas.width || ball.x + ball.radius < 0 || ball.y - ball.radius > canvas.height || ball.y + ball.radius < 0) { ball.x = canvas.width / 2; ball.y = canvas.height; ball.vx = Math.random() * 2 - 1; ball.vy = Math.random() * -10 - 10; } ball.draw(context); } (function drawFrame () { window.requestAnimationFrame(drawFrame, canvas); context.clearRect(0, 0, canvas.width, canvas.height); balls.forEach(draw); }()); }; </script> </body> </html>
3.无限屏幕
这个概念很简单,是对重新生成方法的拓展。就是当目标从右侧出去,他讲从左侧进入。
03-ship-sim-2.html
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!doctype html> <html> <head> <meta charset="utf-8"> <title>Ship Sim 2</title> <link rel="stylesheet" href="../include/style.css"> <style> #canvas { background-color: #000000; } </style> </head> <body> <header> Example from <a href="http://amzn.com/1430236655?tag=html5anim-20"><em>Foundation HTML5 Animation with JavaScript</em></a> </header> <canvas id="canvas" width="400" height="400"></canvas> <aside>Press left and right arrow keys to rotate ship, up to add thrust.</aside> <script src="../include/utils.js"></script> <script src="./classes/ship.js"></script> <script> window.onload = function () { var canvas = document.getElementById('canvas'), context = canvas.getContext('2d'), ship = new Ship(), vr = 0, vx = 0, vy = 0, thrust = 0; ship.x = canvas.width / 2; ship.y = canvas.height / 2; window.addEventListener('keydown', function (event) { switch (event.keyCode) { case 37: //left vr = -3; break; case 39: //right vr = 3; break; case 38: //up thrust = 0.05; ship.showFlame = true; break; } }, false); window.addEventListener('keyup', function () { vr = 0; thrust = 0; ship.showFlame = false; }, false); (function drawFrame () { window.requestAnimationFrame(drawFrame, canvas); context.clearRect(0, 0, canvas.width, canvas.height); ship.rotation += vr * Math.PI / 180; var angle = ship.rotation, //in radians ax = Math.cos(angle) * thrust, ay = Math.sin(angle) * thrust, left = 0, right = canvas.width, top = 0, bottom = canvas.height; vx += ax; vy += ay; ship.x += vx; ship.y += vy; //screen wrapping if (ship.x - ship.width / 2 > right) { ship.x = left - ship.width / 2; } else if (ship.x + ship.width / 2 < left) { ship.x = right + ship.width / 2; } if (ship.y - ship.height / 2 > bottom) { ship.y = top - ship.height / 2; } else if (ship.y < top - ship.height / 2) { ship.y = bottom + ship.height / 2; } ship.draw(context); }()); }; </script> </body> </html>
4.反弹
一.反弹
当一个球体的边界碰到左边的边界,重新设置球体的x轴的速度为反向,Y不变,这样就实现了反弹。
04-bouncing-1.html
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!doctype html> <html> <head> <meta charset="utf-8"> <title>Bouncing 1</title> <link rel="stylesheet" href="../include/style.css"> </head> <body> <header> Example from <a href="http://amzn.com/1430236655?tag=html5anim-20"><em>Foundation HTML5 Animation with JavaScript</em></a> </header> <canvas id="canvas" width="400" height="400"></canvas> <script src="../include/utils.js"></script> <script src="./classes/ball.js"></script> <script> window.onload = function () { var canvas = document.getElementById('canvas'), context = canvas.getContext('2d'), ball = new Ball(), vx = Math.random() * 10 - 5, vy = Math.random() * 10 - 5; ball.x = canvas.width / 2; ball.y = canvas.height / 2; (function drawFrame () { window.requestAnimationFrame(drawFrame, canvas); context.clearRect(0, 0, canvas.width, canvas.height); var left = 0, right = canvas.width, top = 0, bottom = canvas.height; ball.x += vx; ball.y += vy; if (ball.x + ball.radius > right) { ball.x = right - ball.radius; vx *= -1; } else if (ball.x - ball.radius < left) { ball.x = left + ball.radius; vx *= -1; } if (ball.y + ball.radius > bottom) { ball.y = bottom - ball.radius; vy *= -1; } else if (ball.y - ball.radius < top) { ball.y = top + ball.radius; vy *= -1; } ball.draw(context); }()); }; </script> </body> </html>
二.反弹能量减少
先前的实例是建立在反弹能量不减少的情况,上例系数为-1,而生活中,反弹都会流失一部分能量,所以系数的绝对值是要小于1的,0.7是一个比较逼真的数字。
05-bouncing-2.html
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!doctype html> <html> <head> <meta charset="utf-8"> <title>Bouncing 2</title> <link rel="stylesheet" href="../include/style.css"> </head> <body> <header> Example from <a href="http://amzn.com/1430236655?tag=html5anim-20"><em>Foundation HTML5 Animation with JavaScript</em></a> </header> <canvas id="canvas" width="400" height="400"></canvas> <script src="../include/utils.js"></script> <script src="./classes/ball.js"></script> <script> window.onload = function () { var canvas = document.getElementById('canvas'), context = canvas.getContext('2d'), ball = new Ball(), vx = Math.random() * 10 - 5, vy = Math.random() * 10 - 5, bounce = -0.7, gravity = 0.1; ball.x = canvas.width / 2; ball.y = canvas.height / 2; (function drawFrame () { window.requestAnimationFrame(drawFrame, canvas); context.clearRect(0, 0, canvas.width, canvas.height); var left = 0, right = canvas.width, top = 0, bottom = canvas.height; vy += gravity; ball.x += vx; ball.y += vy; if (ball.x + ball.radius > right) { ball.x = right - ball.radius; vx *= bounce; } else if (ball.x - ball.radius < left) { ball.x = left + ball.radius; vx *= bounce; } if (ball.y + ball.radius > bottom) { ball.y = bottom - ball.radius; vy *= bounce; } else if (ball.y - ball.radius < top) { ball.y = top + ball.radius; vy *= bounce; } ball.draw(context); }()); }; </script> </body> </html>