[js高手之路]html5 canvas動畫教程 - 邊界判斷與小球粒子模擬噴泉,散彈效果


備注:本文后面的代碼,如果加載了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>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM