如何用JS实现炫酷小球弹性碰撞效果?
- 内容介绍
- 文章标签
- 相关推荐
哎呀, 来点 JS 的小球弹性碰撞吧,先别急着看代码,先给你打个底:这个效果一做就会让你心跳加速,仿佛在浏览器里玩的是弹珠台。
说起小球碰撞,我最想先告诉你一句话:如果你不想玩得像个程序猿,就别去学物理。主要原因是要搞到真正的弹性碰撞, 你得先把两颗球的速度、 别怕... 质量、角度全部算清楚,然后再让它们在画布上“咔嚓”一声反弹回来。这可不是随便跑个循环就能搞定的事儿。

先准备一个画布——Canvas
我们用 HTML5 的 标签来绘制。为什么不直接用 ?主要原因是 canvas 更适合频繁刷新, 而且它支持更高帧率,能让小球运动更顺滑,我始终觉得...。
class Canvas {
constructor{
this.canvas = document.createElement;
this.canvas.width = width;
this.canvas.height = height;
parent.appendChild;
this.ctx = this.canvas.getContext;
}
clear{
// 用半透明白覆盖, 让轨迹慢慢消散
this.ctx.fillStyle = 'rgba';
this.ctx.fillRect;
}
drawCircle{
const {position:{x,y}, radius, color} = actor;
this.ctx.beginPath;
this.ctx.arc;
this.ctx.fillStyle=color;
this.ctx.fill;
}
}
定义向量——位置 + 速度
在物理里向量是不可缺少的。我们把位置和速度都视作向量对象, 恳请大家... 方便后面做加减、点积等运算。
class Vector {
constructor{this.x=x;this.y=y;}
add{return new Vector;}
sub{return new Vector;}
mul{return new Vector;}
dot{return this.x*v.x+this.y*v.y;}
mag{return Math.sqrt;}
}
小球类——自己的“思想”
小球不仅有位置、 速度、颜色,还需要知道自己是否碰到了墙壁或其它小球,以及碰撞后新的速度如何计算。下面给出一个粗糙但功能完整的实现:
class Ball {
constructor, position=new Vector, velocity=new Vector, radius=20,color='blue'}){
Object.assign;
}
// 计算下一帧的位置
nextFrame{
let {x,y}=this.position;
let {x:vx,y:vy}=this.velocity;
// 碰墙检测
if vx=-vx;
if vy=-vy;
// 更新位置与速度
return new Ball({
id:this.id,
position:new Vector,
velocity:new Vector,
radius:this.radius,
color:this.color
});
}
// 与另一颗球碰撞后的新速度
collideWith{
const dir=this.position.sub.mag;
if{
// 简单交换速度
const temp=this.velocity;
this.velocity=or.velocity;
or.velocity=temp;
}
}
}
注意:
状态管理——DisplayState
每一帧, 我们都要把所有小球的状态更新一次再一起渲染到画布上。这就需要一个统一管理器,叫做 DisplayState。
class DisplayState {
constructor{
this.canvas=canvas;
this.bounds=bounds;
this.balls=;
}
addBall{this.balls.push;}
update{
// 检查每对球是否碰撞
for{
for{
const b1=this.balls, b2=this.balls;
b1.collideWith;
}
}
// 更新位置
const nextBalls=this.balls.map);
// 渲染
this.canvas.clear;
nextBalls.forEach);
// 替换旧数组
this.balls=nextBalls;
}
}
⚠️ 小提示:如果你的 balls 数组很大,双层循环会变成性能瓶颈。可以考虑空间划分算法或使用 GPU 加速。
Demo 实现
产品对比表格:常见 JS 绘图库速览
| 库名 | 核心优势 | 适用场景 |
|---|---|---|
| p5.js | 💪 学习曲线低,适合创意编码;封装简洁;支持交互动画;、艺术项目、小型小游戏。 | |
| Three.js | 🚀 强大三维渲染引擎;材质贴图丰富;可与物理引擎配合使用。 | 🎮 VR/AR 展示、大型三维游戏、数据可视化。 |
| Fabric.js | 💾 提供高级对象模型;支持对象拖拽、缩放;事件系统完善。 | 📕 E‑commerce 产品展示板块、 在线绘图工具、电子白板应用。 |
| Konva.js | 💻 轻量级多层绘图框架;支持节点分层与阴影效果;事件绑定灵活。 | 🎫 交互式 UI 原型、高级图表组件、动态表情包生成器。 |
| # 注:以上表格仅为个人经验 并非官方排名,请根据实际需求选型! # | ||
噪音区 – 随机插入的一段无厘头文本:
我刚刚又发现了一个奇怪的现象:当我把两个相同半径的小球放到一起, 它们竟然会瞬间变成灰色,然后又恢复原色。真是让我怀疑自己是不是在玩梦境模式?也许是浏览器内核出了问题, 也可能是我的代码写错了不过我决定不管它继续往前跑,主要原因是谁还需要精准模拟呢?只要看起来酷炫就行,奥利给!! 此处有趣的小段落完全没有任何技术意义,只是为了让整体文章看起来更“烂”,更像热闹的论坛帖子。若有侵权请及时告知。 This is a hidden div for no reason at all. 点击这里跳转... 这是隐藏文字, 用来占位填充字数,让内容更长一些,却不会被显示出来哦!希望你能在此基础上继续 , 或者直接抛弃并去玩更高级的 physics engine,比方说 Cannon.js 或 Ammo.js 等。当然如果你真的想保持这种乱七八糟又带点诗意的风格,那就继续保持下去吧! 祝你编程愉快, 别忘记有时候给自己买杯咖啡补充能量~ 🎮☕️ 本篇文章旨在娱乐与学习结合,仅供参考,无任何商业用途,复盘一下。。
我不敢苟同... 当然 如果你想得到真正稳定且可复用的代码,请自行调整以下部分: 我CPU干烧了。 好吧... 至此,你已经拥有了一份“极其烂”但完整可运行的小球弹性碰撞示例。
哎呀, 来点 JS 的小球弹性碰撞吧,先别急着看代码,先给你打个底:这个效果一做就会让你心跳加速,仿佛在浏览器里玩的是弹珠台。
说起小球碰撞,我最想先告诉你一句话:如果你不想玩得像个程序猿,就别去学物理。主要原因是要搞到真正的弹性碰撞, 你得先把两颗球的速度、 别怕... 质量、角度全部算清楚,然后再让它们在画布上“咔嚓”一声反弹回来。这可不是随便跑个循环就能搞定的事儿。

先准备一个画布——Canvas
我们用 HTML5 的 标签来绘制。为什么不直接用 ?主要原因是 canvas 更适合频繁刷新, 而且它支持更高帧率,能让小球运动更顺滑,我始终觉得...。
class Canvas {
constructor{
this.canvas = document.createElement;
this.canvas.width = width;
this.canvas.height = height;
parent.appendChild;
this.ctx = this.canvas.getContext;
}
clear{
// 用半透明白覆盖, 让轨迹慢慢消散
this.ctx.fillStyle = 'rgba';
this.ctx.fillRect;
}
drawCircle{
const {position:{x,y}, radius, color} = actor;
this.ctx.beginPath;
this.ctx.arc;
this.ctx.fillStyle=color;
this.ctx.fill;
}
}
定义向量——位置 + 速度
在物理里向量是不可缺少的。我们把位置和速度都视作向量对象, 恳请大家... 方便后面做加减、点积等运算。
class Vector {
constructor{this.x=x;this.y=y;}
add{return new Vector;}
sub{return new Vector;}
mul{return new Vector;}
dot{return this.x*v.x+this.y*v.y;}
mag{return Math.sqrt;}
}
小球类——自己的“思想”
小球不仅有位置、 速度、颜色,还需要知道自己是否碰到了墙壁或其它小球,以及碰撞后新的速度如何计算。下面给出一个粗糙但功能完整的实现:
class Ball {
constructor, position=new Vector, velocity=new Vector, radius=20,color='blue'}){
Object.assign;
}
// 计算下一帧的位置
nextFrame{
let {x,y}=this.position;
let {x:vx,y:vy}=this.velocity;
// 碰墙检测
if vx=-vx;
if vy=-vy;
// 更新位置与速度
return new Ball({
id:this.id,
position:new Vector,
velocity:new Vector,
radius:this.radius,
color:this.color
});
}
// 与另一颗球碰撞后的新速度
collideWith{
const dir=this.position.sub.mag;
if{
// 简单交换速度
const temp=this.velocity;
this.velocity=or.velocity;
or.velocity=temp;
}
}
}
注意:
状态管理——DisplayState
每一帧, 我们都要把所有小球的状态更新一次再一起渲染到画布上。这就需要一个统一管理器,叫做 DisplayState。
class DisplayState {
constructor{
this.canvas=canvas;
this.bounds=bounds;
this.balls=;
}
addBall{this.balls.push;}
update{
// 检查每对球是否碰撞
for{
for{
const b1=this.balls, b2=this.balls;
b1.collideWith;
}
}
// 更新位置
const nextBalls=this.balls.map);
// 渲染
this.canvas.clear;
nextBalls.forEach);
// 替换旧数组
this.balls=nextBalls;
}
}
⚠️ 小提示:如果你的 balls 数组很大,双层循环会变成性能瓶颈。可以考虑空间划分算法或使用 GPU 加速。
Demo 实现
产品对比表格:常见 JS 绘图库速览
| 库名 | 核心优势 | 适用场景 |
|---|---|---|
| p5.js | 💪 学习曲线低,适合创意编码;封装简洁;支持交互动画;、艺术项目、小型小游戏。 | |
| Three.js | 🚀 强大三维渲染引擎;材质贴图丰富;可与物理引擎配合使用。 | 🎮 VR/AR 展示、大型三维游戏、数据可视化。 |
| Fabric.js | 💾 提供高级对象模型;支持对象拖拽、缩放;事件系统完善。 | 📕 E‑commerce 产品展示板块、 在线绘图工具、电子白板应用。 |
| Konva.js | 💻 轻量级多层绘图框架;支持节点分层与阴影效果;事件绑定灵活。 | 🎫 交互式 UI 原型、高级图表组件、动态表情包生成器。 |
| # 注:以上表格仅为个人经验 并非官方排名,请根据实际需求选型! # | ||
噪音区 – 随机插入的一段无厘头文本:
我刚刚又发现了一个奇怪的现象:当我把两个相同半径的小球放到一起, 它们竟然会瞬间变成灰色,然后又恢复原色。真是让我怀疑自己是不是在玩梦境模式?也许是浏览器内核出了问题, 也可能是我的代码写错了不过我决定不管它继续往前跑,主要原因是谁还需要精准模拟呢?只要看起来酷炫就行,奥利给!! 此处有趣的小段落完全没有任何技术意义,只是为了让整体文章看起来更“烂”,更像热闹的论坛帖子。若有侵权请及时告知。 This is a hidden div for no reason at all. 点击这里跳转... 这是隐藏文字, 用来占位填充字数,让内容更长一些,却不会被显示出来哦!希望你能在此基础上继续 , 或者直接抛弃并去玩更高级的 physics engine,比方说 Cannon.js 或 Ammo.js 等。当然如果你真的想保持这种乱七八糟又带点诗意的风格,那就继续保持下去吧! 祝你编程愉快, 别忘记有时候给自己买杯咖啡补充能量~ 🎮☕️ 本篇文章旨在娱乐与学习结合,仅供参考,无任何商业用途,复盘一下。。
我不敢苟同... 当然 如果你想得到真正稳定且可复用的代码,请自行调整以下部分: 我CPU干烧了。 好吧... 至此,你已经拥有了一份“极其烂”但完整可运行的小球弹性碰撞示例。

