[js高手之路]html5 canvas动画教程 - 边界判断与反弹

本文介绍如何使用HTML5 Canvas实现小球碰撞边界后反弹的效果,并扩展到多个小球的同时处理,通过调整速度方向来模拟真实的物理反弹。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

备注:本文后面的代码,如果加载了ball.js,那么请使用这篇文章[js高手之路] html5 canvas动画教程 - 匀速运动的ball.js代码.

边界反弹:

当小球碰到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                 vx = Math.random() * 2 + 5,
16                 vy = Math.random() * 2 + 5;
17             ball.fill(oGc);
18             ( function move(){
19                 oGc.clearRect( 0, 0, width, height );
20                 ball.x += vx;
21                 ball.y += vy;
22                 ball.fill( oGc );
23 
24                 if ( ball.x < ball.radius ) { //碰到左边的边界
25                     ball.x = ball.radius;
26                     vx = -vx;
27                 }else if ( ball.y < ball.radius ){
28                     ball.y = ball.radius;
29                     vy = -vy;
30                 }else if ( ball.x > width - ball.radius ){
31                     ball.x = width - ball.radius;
32                     vx = -vx;
33                 }else if ( ball.y > height - ball.radius ){
34                     ball.y = height - ball.radius;
35                     vy = -vy;
36                 }
37                 requestAnimationFrame( move );
38             } )();
39         }
40     </script>
41 </head>
42 
43 <body>
44     <canvas id="canvas" width="1200" height="600"></canvas>
45 </body>

 原理跟之前写的文章[js高手之路]html5 canvas动画教程 - 边界判断与小球粒子模拟喷泉,散弹效果差不多,只是在碰到边界的时候,把速度调成反向的,小球就会反弹.

<head> <meta charset='utf-8' /> <style> #canvas { border: 1px dashed #aaa; } </style> <script> function Ball(x, y, r, color) { this.x = x || 0; this.y = y || 0; this.radius = r || 20; this.color = color || '#09f'; } Ball.prototype = { constructor: Ball, stroke: function (cxt) { cxt.strokeStyle = this.color; cxt.beginPath(); cxt.arc(this.x, this.y, this.radius, 0, 2 * Math.PI); cxt.closePath(); cxt.stroke(); }, fill: function (cxt) { cxt.fillStyle = this.color; cxt.beginPath(); cxt.arc(this.x, this.y, this.radius, 0, 2 * Math.PI); cxt.closePath(); cxt.fill(); } } </script> <script> window.onload = function () { var oCanvas = document.querySelector("#canvas"), oGc = oCanvas.getContext('2d'), width = oCanvas.width, height = oCanvas.height, ball = new Ball(width / 2, height / 2), vx = Math.random() * 2 + 5, vy = Math.random() * 2 + 5; ball.fill(oGc); (function move() { oGc.clearRect(0, 0, width, height); ball.x += vx; ball.y += vy; ball.fill(oGc); if (ball.x < ball.radius) { //碰到左边的边界 ball.x = ball.radius; vx = -vx; } else if (ball.y < ball.radius) { ball.y = ball.radius; vy = -vy; } else if (ball.x > width - ball.radius) { ball.x = width - ball.radius; vx = -vx; } else if (ball.y > height - ball.radius) { ball.y = height - ball.radius; vy = -vy; } requestAnimationFrame(move); })(); } </script> </head> <body> <canvas id="canvas" width="1200" height="600"></canvas> </body>
run code

 多个物体的反弹

 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                     ball.x += ball.vx;
30                     ball.y += ball.vy;
31                     ball.fill(oGc);
32 
33                     if (ball.x < ball.radius) { //碰到左边的边界
34                         ball.x = ball.radius;
35                         ball.vx = -ball.vx;
36                     } else if (ball.y < ball.radius) {
37                         ball.y = ball.radius;
38                         ball.vy = -ball.vy;
39                     } else if (ball.x > width - ball.radius) {
40                         ball.x = width - ball.radius;
41                         ball.vx = -ball.vx;
42                     } else if (ball.y > height - ball.radius) {
43                         ball.y = height - ball.radius;
44                         ball.vy = -ball.vy;
45                     }
46                 });
47                 requestAnimationFrame(move);
48             })();
49         }
50     </script>
51 </head>
52 
53 <body>
54     <canvas id="canvas" width="1200" height="600"></canvas>
55 </body>

原理是一样的,只是把坐标和速度的判断,基于一个个小球对象.

 

<head> <meta charset='utf-8' /> <style> #canvas { border: 1px dashed #aaa; } </style> <script> function Ball(x, y, r, color) { this.x = x || 0; this.y = y || 0; this.radius = r || 20; this.color = color || '#09f'; } Ball.prototype = { constructor: Ball, stroke: function (cxt) { cxt.strokeStyle = this.color; cxt.beginPath(); cxt.arc(this.x, this.y, this.radius, 0, 2 * Math.PI); cxt.closePath(); cxt.stroke(); }, fill: function (cxt) { cxt.fillStyle = this.color; cxt.beginPath(); cxt.arc(this.x, this.y, this.radius, 0, 2 * Math.PI); cxt.closePath(); cxt.fill(); } } </script> <script> window.onload = function () { var oCanvas = document.querySelector("#canvas"), oGc = oCanvas.getContext('2d'), width = oCanvas.width, height = oCanvas.height, balls = [], n = 50; function getRandColor() { return '#' + (function (color) { return (color += '0123456789abcdef'[Math.floor(Math.random() * 16)]) && (color.length == 6) ? color : arguments.callee(color); })(''); } for (var i = 0; i < n; i++) { var ball = new Ball(width / 2, height / 2, 20, getRandColor()); ball.vx = (Math.random() * 2 - 1) * 5; ball.vy = (Math.random() * 2 - 1) * 5; balls.push(ball); } (function move() { oGc.clearRect(0, 0, width, height); balls.forEach(function (ball) { ball.x += ball.vx; ball.y += ball.vy; ball.fill(oGc); if (ball.x < ball.radius) { //碰到左边的边界 ball.x = ball.radius; ball.vx = -ball.vx; } else if (ball.y < ball.radius) { ball.y = ball.radius; ball.vy = -ball.vy; } else if (ball.x > width - ball.radius) { ball.x = width - ball.radius; ball.vx = -ball.vx; } else if (ball.y > height - ball.radius) { ball.y = height - ball.radius; ball.vy = -ball.vy; } }); requestAnimationFrame(move); })(); } </script> </head> <body> <canvas id="canvas" width="1200" height="600"></canvas> </body>
run code
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值