在 Canvas 中让弹跳球动起来:改变重力和反弹系数的 JavaScript 实验

プログラミング・Web開発カテゴリを表すパンダのイラスト 编程・Web开发

关于本文
本文是通过利用生成式 AI 的自动化生成流程创建的。
我们在查阅了 MDN 的 Canvas 动画、requestAnimationFrame 以及减少动态效果的第一手资料后,制作了这款可改变重力和反弹系数的 JavaScript 教学课件。

验证状态:📘 已确认官方信息、V8 语法和数值计算 / 浏览器实机未验证
2026年10月31日,我们将 Daily Code 的三个文件保存并读取回 GitHub,检查了下落、碰撞、反弹以及在地面静止的条件。GitHub Pages 的访问、WordPress 的蓝色边框、以及移动端和打印/PDF 的实际显示效果尚未验证。

通过让小球落下并弹起,你可以亲眼看到在 JavaScript 中处理速度、位置和加速度的意义。这是一个能够逐一对比改变重力与改变反弹系数时差异的教学课件。

本次可以实现的功能

项目条件
支持情况支持 Canvas 2D 和 JavaScript 的浏览器(实机未验证)
技术Canvas API / requestAnimationFrame
费用无需外部库、付费 API 或登录
通信仅加载页面。不向外部发送操作结果
操作播放・停止・前进0.2秒・重置・滑块
数据虚拟球。不含个人信息或位置信息

先试一试:让球弹跳起来

🔷 只需3项操作即可体验
🏀 打开 Canvas 弹跳演示(公开・浏览器运行状态未确认)
📘 完成版 HTML・JavaScript・README

  1. 点击“播放”,观察球下落和弹跳的过程。
  2. 将“恢复系数”从 0.80 改为 0.45。
  3. 点击“重置”,然后从相同高度再次开始运动。

🟦 操作后请看这里
请同时确认绘图区域下方的“距地面高度 (px)”和“碰撞次数”。如果觉得运动难以看清,可以使用“前进0.2秒”作为静态画面追踪变化。

条件预期变化
反弹系数 0.80弹跳较高
反弹系数 0.45弹跳较低
重力 600 → 1000 px/s²更快到达地面
暂停保留位置和次数
前进 0.2 秒推进计算并显示静止状态

这些是根据代码预测的期望结果,并非实际浏览器的测量结果。 每次比较时,请点击“重置”以统一初始条件。

为什么球会弹跳

Canvas 是绘制圆形和线条的区域。JavaScript 会更新球的当前位置并重复重新绘制,从而呈现出运动效果。本教程中使用的是屏幕像素制作的简化物理模型。

若将垂直方向的速度设为 vy、位置设为 y、加速度设为 g、经过时间设为 dt,则处理的核心如下:

vy = vy + g * dt;          // 速度を更新する
y = y + vy * dt;          // 位置を更新する
if (y >= floor - radius) {
  y = floor - radius;     // 床の位置に戻す
  vy = -vy * restitution; // 反対方向へ跳ねる
}

此代码仅为展示思路的片段,并非可独立运行的完整版本。Daily Code 的 JavaScript 主体包含在球静止于地面后不再增加碰撞次数的处理、停止计时器以及对减少动画运动设置的支持等。

flowchart LR
  A["再生・コマ送り"] --> B["速度・位置の更新"]
  B --> C{"床に接した?"}
  C -->|はい| D["反発係数で速度を反転"]
  C -->|いいえ| E["その位置を使用"]
  D --> F["Canvasに再描画"]
  E --> F
  F --> G["高さ・衝突回数を更新"]

浏览器的 requestAnimationFrame 是一种请求在下一次重新绘制前调用处理程序的 API。为了防止其在高刷新率屏幕上显得异常迅捷,它会使用自上一次以来的经过时间。如果屏幕被隐藏,则会停止播放,同时抑制因经过时间过长而导致的突然位移。

修改一处进行对比

将恢复系数固定为0.80,仅将重力设置从600 px/s²更改为1000 px/s²。每次都点击“重置”以统一初始条件。

比较重力预期结果
更改前600 px/s²基准下落速度
更改后1000 px/s²更快到达地面

这里改变的只有重力。如果同时改变恢复系数,将难以判断是哪个因素造成了差异。

px/s²是使用画布像素坐标的教学单位。它并不直接表示地球的重力加速度。不能用于实际材料或机械的安全计算。

尊重减少动画的设置

⚠️ 不适应连续动画时
当操作系统或浏览器的减少动态效果设置(prefers-reduced-motion: reduce)有效时,连续播放将被禁用。你可以通过“前进0.2秒”逐帧观察静态图像。打开页面时不会自动播放。

普通模式也可以通过“停止”按钮中断,切换到其他标签页时会停止播放。在智能手机上,内部画布坐标 720×360 会通过 CSS 进行缩放,因此屏幕下方的像素值与屏幕的物理像素数不一致。

在自己的电脑上运行

HTML与JavaScript保存在同一个文件夹中,并在浏览器中打开HTML。如果需要,可以通过以下命令启动本地服务器并访问 localhost。

python3 -m http.server 8000 --bind 127.0.0.1

要打开的URL是 http://127.0.0.1:8000/ 。如果Windows上可以使用Python Launcher,也可以通过 py -3 -m http.server 8000 –bind 127.0.0.1 来运行。按 Ctrl+C 退出。

如果运行不正常

症状确认
一直处于加载状态app.js的位置及控制台(Console)错误
小球不移动播放操作、减少动画设置
碰撞次数没有增加是否推进到了小球触底
比较结果不稳定是否重置并匹配了初始条件
看起来很小Canvas内部坐标与CSS显示宽度的差异

如何在工作和学习中使用?

它可以应用作游戏、学习教材以及展示状态变化的UI基础。但是,反弹效果看起来正确并不意味着验证了现实中的物理现象。实际业务中的计算需要与实测值进行核对、单位换算、边界条件以及误差评估。

比较接触地面瞬间的位置与速度

在球触地瞬间,不仅需要弹回的速度,还需要将其处理回不会超出地面的位置。由于向屏幕下方移动的球是一个圆,如果将其中心坐标设为与地面高度相同,则下半部分会陷入地面。中心位置必须放在地面高度减去半径的位置。如果只修正位置而保持向下的速度不变,它将在下一次更新时再次试图进入地面。相反,如果不反转速度并修正位置,它可能会表现得像从地面下方弹回一样。这就是文章中的代码片段要进行这两种处理的原因。

恢复系数是教学用的一个数值,表示碰撞前瞬间的速度在碰撞后保留了多少。0.80意味着保留了比较大的速度,而0.45则较小。不能因为恢复系数减半,弹起的高度就简单地减半。高度还受到速度、加速度和经过时间的影响。请观察从相同高度落下、固定重力、仅改变系数时的区别。如果在比较之前没有重置,残留的上一次速度可能会导致结果无法解读。

可以预料,增大重力会缩短到达地面的时间。但是,如果同时改变恢复系数,就会分不清到底是哪个设置导致了弹跳方式的区别。在文章的对照表中,当把重力从600改到1000时,恢复系数固定为0.80。此时,请关注下落过程中速度的增长方式,不要把碰撞次数作为唯一的成功条件。在接下来的实验中,将重力改回600,只把恢复系数降低到0.45。如果将这两个实验分开,将更容易理解加速度的变化与碰撞时的能量损失之间的差异。

观察时间的推进方式

屏幕上的运动看起来是连续的,但程序是以极短的时间间隔更新速度和位置的。如果不考虑表示经过时间的dt,外观速度可能会因设备渲染次数的不同而有所变化。如果在切换标签页经过较长时间后返回,球在返回的瞬间突然表现得像是穿透了地面,这可能是由于将较长的时间合并计算所致。本教材采用了抑制这种影响的思路,但并非在所有环境下都实际测量出了相同的结果。

在推进0.2秒的操作中,并非观察连续的画面,而是可以作为静态图像来观察推进了短时间后的结果。如果尚未触地,碰撞次数没有增加是正常的。如果在接触地面后碰撞次数持续增加,则需要确认是否将静止状态每次都算作了一次新的碰撞。不仅要看数值,还要将其与距离地面的高度同时观察,这样更容易理解状态。给静止的球强行赋予速度,与作为计算结果而停止,这两者也是不同的。

本教材中的px/s²是在Canvas内部坐标中设置的加速度。它并非现实中的重力或机械材料特性的测量值。虽然它可以应用于游戏或学习教材的UI,但不能用于计算来评估现实装置的安全性。对于不擅长观察动态的用户,可以通过逐帧播放和状态显示来在相同条件下进行观察。在应用于实际业务时,不要将重要信息仅仅局限于屏幕的颜色和动态,这也是一个重要的观点。

官方信息与参考资料

官方资料确认日期:2026年10月31日。虽然执行了GitHub源代码读取、V8语法和计算检查,但尚未确认Pages发布、实际浏览器运行情况以及WordPress的蓝色边框显示。

GitHub示例

文档信息

文章??
在 Canvas 中让弹跳球动起来:改变重力和反弹系数的 JavaScript 实验
?布日期
更新日期
来源
https://papanda925.com/?p=18450&lang=zh

?可: ?于本站?有相??利的正文及原??表,除非?有?明,可依据 CC BY 4.0 使用。本文可能包含使用生成式AI?建或??的内容。若代??有?可声明,或?接的GitHub???定了?可,?代?以??可?准。引用内容、第三方?料、?片及商?不在本?可范?内。 使用政策

标题和URL已复制