備注:本文后面的代碼,如果加載了ball.js,那么請使用這篇文章[js高手之路] html5 canvas動畫教程 - 勻速運動的ball.js代碼.
本文,我們要做點有意思的效果,首先,來一個簡單的邊界判斷,所謂邊界判斷:就是把物體的運動限定在一個范圍內.我們先來一個簡單的實例,在canvas上生成一個小球,小球的初始位置是在canvas的正中間,然后通過鍵盤的上下左右來移動小球的位置,如果小球碰到canvas的左邊,那么不能再向左運動,其他方向同理.
要實現這個效果,只需要一個邊界判斷,即可。
1 function checkBorder() { 2 if ( ball.x < ball.radius ) { //碰到左邊界 3 ball.x = ball.radius; 4 } else if ( ball.y < ball.radius ) { //碰到上邊界 5 ball.y = ball.radius; 6 } else if ( ball.x > width - ball.radius ) { //碰到右邊界 7 ball.x = width - ball.radius; 8 }else if ( ball.y > height - ball.radius ){ 9 ball.y = height - ball.radius; 10 } 11 }
左邊界:只要判斷小球的圓心x 如果小於小球的半徑,那肯定是碰到了左邊界,我們就讓小球的中心x等於小球的半徑。
右邊界:只要判斷小球的圓心x 如果大於canvas的寬度減去小球的半徑,那肯定是碰到了右邊界,我們就讓小球的中心x等於canvas的寬度減去小球的半徑
其他上下邊界跟左右是同理。
完整的實例代碼:
1 <head> 2 <meta charset='utf-8' /> 3 <style> 4 #canvas { 5 border: 1px dashed #aaa; 6 } 7 </style> 8 <script src="./ball.js"></script> 9 <script> 10 window.onload = function () { 11 var oCanvas = document.querySelector("#canvas"), 12 oGc = oCanvas.getContext('2d'), 13 width = oCanvas.width, height = oCanvas.height, 14 ball = new Ball(width / 2, height / 2); 15 ball.fill( oGc ); 16 addEventListener("keydown", function (ev) { 17 oGc.clearRect(0, 0, width, height); 18 var oEvent = ev || event; 19 switch (oEvent.keyCode) { 20 case 37: 21 ball.x -= 5; 22 checkBorder(); 23 ball.fill(oGc); 24 break; 25 case 39: 26 ball.x += 5; 27 checkBorder(); 28 ball.fill(oGc); 29 break; 30 case 38: 31 ball.y -= 5; 32 checkBorder(); 33 ball.fill(oGc); 34 break; 35 case 40: 36 ball.y += 5; 37 checkBorder(); 38 ball.fill(oGc); 39 break; 40 } 41 }, false); 42 function checkBorder() { 43 if ( ball.x < ball.radius ) { //碰到左邊界 44 ball.x = ball.radius; 45 } else if ( ball.y < ball.radius ) { //碰到上邊界 46 ball.y = ball.radius; 47 } else if ( ball.x > width - ball.radius ) { //碰到右邊界 48 ball.x = width - ball.radius; 49 }else if ( ball.y > height - ball.radius ){ 50 ball.y = height - ball.radius; 51 } 52 } 53 } 54 </script> 55 </head> 56 57 <body> 58 <canvas id="canvas" width="1200" height="600"></canvas> 59 </body>
邊界穿透:
如果小球向左運動,且完全超出左邊界,我們就讓他從右邊出來,如果小球向右運動,且完全超出右邊界,我們就讓他從左邊出來。上下方向同理
1 <head> 2 <meta charset='utf-8' /> 3 <style> 4 #canvas { 5 border: 1px dashed #aaa; 6 } 7 </style> 8 <script src="./ball.js"></script> 9 <script> 10 window.onload = function () { 11 var oCanvas = document.querySelector("#canvas"), 12 oGc = oCanvas.getContext('2d'), 13 width = oCanvas.width, height = oCanvas.height, 14 ball = new Ball(width / 2, height / 2); 15 ball.fill(oGc); 16 addEventListener("keydown", function (ev) { 17 oGc.clearRect(0, 0, width, height); 18 var oEvent = ev || event; 19 switch (oEvent.keyCode) { 20 case 37: 21 ball.x -= 5; 22 checkBorder(); 23 ball.fill(oGc); 24 break; 25 case 39: 26 ball.x += 5; 27 checkBorder(); 28 ball.fill(oGc); 29 break; 30 case 38: 31 ball.y -= 5; 32 checkBorder(); 33 ball.fill(oGc); 34 break; 35 case 40: 36 ball.y += 5; 37 checkBorder(); 38 ball.fill(oGc); 39 break; 40 } 41 }, false); 42 function checkBorder() { 43 if (ball.x < -ball.radius) { //完全超出左邊界 44 ball.x = width + ball.radius; //讓球從右邊出來 45 } else if (ball.y < -ball.radius) { //完全超出上邊界 46 ball.y = height + ball.radius;//讓球從下面出來 47 } else if (ball.x > width + ball.radius) { //完全超出右邊界 48 ball.x = -ball.radius;//讓球從左邊出來 49 } else if (ball.y > height + ball.radius) {//完全超出下邊界 50 ball.y = -ball.radius; //讓球從上邊出來 51 } 52 } 53 } 54 </script> 55 </head> 56 57 <body> 58 <canvas id="canvas" width="1200" height="600"></canvas> 59 </body>
散彈效果:
通過canvas的中心點,不停的向四周發射小球,形成散彈的效果.
我不知道你們有沒有這樣的誤區:不停的向四周發射小球,那是不是要不停的創造小球呢?如果你這樣想,程序就算寫出來了,肯定會卡死.
其實我們可以只創建,一定數量的小球,比如( 50, 60. ...100 ),然后當這些小球,完全超出的邊界的時候,再把這些小球的圓心( x, y )設定到最開始的位置,再次隨機x和y方向的速度,就可以達到目的了, 說白了就是,那個完全超出邊界的小球,我們讓他重新回到最初的地方,只是改變了他的顏色和速度,給人感覺就是那個發射小球的地方源源不斷的在發射小球
完整的散彈效果:
1 <head> 2 <meta charset='utf-8' /> 3 <style> 4 #canvas { 5 border: 1px dashed #aaa; 6 } 7 </style> 8 <script src="./ball.js"></script> 9 <script> 10 window.onload = function () { 11 var oCanvas = document.querySelector("#canvas"), 12 oGc = oCanvas.getContext('2d'), 13 width = oCanvas.width, height = oCanvas.height, 14 balls = [], n = 50; 15 function getRandColor() { 16 return '#' + ( function( color ){ 17 return ( color += '0123456789abcdef' [Math.floor( Math.random() * 16 )] ) && ( color.length == 6 ) ? color : arguments.callee( color ); 18 } )( '' ); 19 } 20 for( var i = 0; i < n; i++ ) { 21 var ball = new Ball( width / 2, height / 2, 20, getRandColor() ); 22 ball.vx = ( Math.random() * 2 - 1 ) * 5; 23 ball.vy = ( Math.random() * 2 - 1 ) * 5; 24 balls.push( ball ); 25 } 26 (function move(){ 27 oGc.clearRect( 0, 0, width, height ); 28 balls.forEach( function( ball ){ 29 if ( ball.x < -ball.radius 30 || ball.x > width + ball.radius 31 || ball.y < -ball.radius 32 || ball.y > height + ball.radius ) { 33 ball.x = width / 2; 34 ball.y = height / 2; 35 ball.vx = ( Math.random() * 2 - 1 ) * 5; 36 ball.vy = ( Math.random() * 2 - 1 ) * 5; 37 } 38 ball.x += ball.vx; 39 ball.y += ball.vy; 40 ball.fill( oGc ); 41 } ); 42 requestAnimationFrame( move ); 43 })(); 44 } 45 </script> 46 </head> 47 <body> 48 <canvas id="canvas" width="1200" height="600"></canvas> 49 </body>
我們可以在之前的基礎上,加上重力的影響,實現噴泉的效果
這張圖,看着是不是更像噴泉?
1 <head> 2 <meta charset='utf-8' /> 3 <style> 4 #canvas { 5 border: 1px dashed #aaa; 6 } 7 </style> 8 <script src="./ball.js"></script> 9 <script> 10 window.onload = function () { 11 var oCanvas = document.querySelector("#canvas"), 12 oGc = oCanvas.getContext('2d'), 13 width = oCanvas.width, height = oCanvas.height, 14 balls = [], n = 50, gravity = 0.2; 15 function getRandColor() { 16 return '#' + (function (color) { 17 return (color += '0123456789abcdef'[Math.floor(Math.random() * 16)]) && (color.length == 6) ? color : arguments.callee(color); 18 })(''); 19 } 20 for (var i = 0; i < n; i++) { 21 var ball = new Ball(width / 2, height / 2, 20, getRandColor()); 22 ball.vx = (Math.random() * 2 - 1) * 5; 23 ball.vy = (Math.random() * 2 - 1) * 10; 24 balls.push(ball); 25 } 26 (function move() { 27 oGc.clearRect(0, 0, width, height); 28 balls.forEach(function (ball) { 29 if (ball.x < -ball.radius 30 || ball.x > width + ball.radius 31 || ball.y < -ball.radius 32 || ball.y > height + ball.radius) { 33 ball.x = width / 2; 34 ball.y = height / 2; 35 ball.vx = (Math.random() * 2 - 1) * 5; 36 ball.vy = (Math.random() * 2 - 1) * 10; 37 } 38 ball.x += ball.vx; 39 ball.y += ball.vy; 40 ball.vy += gravity; 41 ball.fill(oGc); 42 }); 43 requestAnimationFrame(move); 44 })(); 45 } 46 </script> 47 </head> 48 49 <body> 50 <canvas id="canvas" width="1200" height="600"></canvas> 51 </body>
還可以通過控制小球的vx, vy,就是x方向和y方向的速度,來限制小球朝某一個方向發射,下面的例子,我們只讓小球朝着x軸的右邊發射
1 <head> 2 <meta charset='utf-8' /> 3 <style> 4 #canvas { 5 border: 1px dashed #aaa; 6 } 7 </style> 8 <script src="./ball.js"></script> 9 <script> 10 window.onload = function () { 11 var oCanvas = document.querySelector("#canvas"), 12 oGc = oCanvas.getContext('2d'), 13 width = oCanvas.width, height = oCanvas.height, 14 balls = [], n = 50; 15 function getRandColor() { 16 return '#' + ( function( color ){ 17 return ( color += '0123456789abcdef' [Math.floor( Math.random() * 16 )] ) && ( color.length == 6 ) ? color : arguments.callee( color ); 18 } )( '' ); 19 } 20 for( var i = 0; i < n; i++ ) { 21 var ball = new Ball( width / 2, height / 2, 20, getRandColor() ); 22 ball.vx = Math.abs( ( Math.random() * 2 - 1 ) * 5 ); 23 ball.vy = ( Math.random() * 2 - 1 ) * 5; 24 balls.push( ball ); 25 } 26 (function move(){ 27 oGc.clearRect( 0, 0, width, height ); 28 balls.forEach( function( ball ){ 29 if ( ball.x < -ball.radius 30 || ball.x > width + ball.radius 31 || ball.y < -ball.radius 32 || ball.y > height + ball.radius ) { 33 ball.x = width / 2; 34 ball.y = height / 2; 35 ball.vx = Math.abs( ( Math.random() * 2 - 1 ) * 5 ); 36 ball.vy = ( Math.random() * 2 - 1 ) * 5; 37 } 38 ball.x += ball.vx; 39 ball.y += ball.vy; 40 ball.fill( oGc ); 41 } ); 42 requestAnimationFrame( move ); 43 })(); 44 } 45 </script> 46 </head> 47 <body> 48 <canvas id="canvas" width="1200" height="600"></canvas> 49 </body>