canvas中实现重力与碰撞反弹的核心是物理公式迭代更新位置、速度、加速度,并做边界及物体间条件判断:重力使vy每帧累加g;触地时y复位且vy反向衰减;左右边界同理;小球间碰撞需检测距离并按动量守恒简化处理。

Canvas 中实现重力与碰撞反弹,核心是用物理公式更新物体位置和速度,再每帧重绘。关键不在“画”,而在“算”——位置、速度、加速度的迭代更新,加上边界和物体间的条件判断。
重力作用:持续向下加速
重力本质是恒定加速度(如 g = 0.3)。每帧给小球的垂直速度(vy)叠加这个值:
-
vy += g;—— 模拟自由下落加速 - 水平速度
vx默认不变(无空气阻力时) - 注意:Canvas 坐标系 y 向下为正,所以重力加速度取正值,无需取负
地面/边界碰撞:速度反向 + 能量损耗
当小球底部触地(y + radius >= canvas.height),需做两件事:
- 把小球“托回”安全位置:
y = canvas.height - radius;(防止因速度过大卡进地面) - 垂直速度反向并衰减:
vy = -vy * damping;(damping如 0.8~0.95,模拟能量损失) - 同理处理左右边界:x 超出范围时修正位置 + 反转
vx
小球间碰撞:动量守恒的简化实现
两个小球碰撞需检测距离是否小于半径和(dx² + dy² )。真实物理涉及角度、质量、法向量,但常见简化如下:
- 先分离两球:沿连线方向将它们轻轻推开,避免下一帧重复触发
- 再交换或按质量加权更新速度分量(若质量相等,可直接交换 x/y 方向的速度投影)
- 更轻量的做法:只反转相对速度在碰撞方向上的分量,其余保持惯性
动画循环:requestAnimationFrame 驱动更新+绘制
所有计算必须放在同一帧内完成,避免视觉跳跃:
- 用
requestAnimationFrame替代setInterval,保证流畅且节电 - 每帧顺序:更新所有小球速度 → 更新所有小球位置 → 检测并响应碰撞 → 清空 canvas → 绘制所有小球
- 清空推荐用
ctx.clearRect(0, 0, width, height);若背景复杂,可考虑仅重绘运动区域或用双缓冲
不复杂但容易忽略:时间步长未固定时,重力累积会随帧率波动。简单项目可忽略;高精度需求建议引入 delta-time 缩放(vy += g * deltaTime),或锁定逻辑帧率。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










