用requestAnimationFrame实现抛物线运动的关键是将物理公式转化为每帧位置更新:x = v₀ₓ×t,y = v₀ᵧ×t − ½gt²,以rAF的timestamp计算Δt并累加总时间t;封装Ball类管理状态与update/render;注意时间单位统一为秒、y轴向下重力取正、避免手动获取时间戳。

用 requestAnimationFrame 实现抛物线运动,核心是把物理公式转化为每帧更新的位置,再用 rAF 驱动平滑渲染。关键不在“怎么调用 rAF”,而在于“怎么算对每一帧的 x 和 y”。
理解抛物线运动的数学模型
理想抛物线由初速度和重力决定。水平方向匀速(x = v₀ₓ × t),竖直方向匀变速(y = v₀ᵧ × t − ½gt²)。时间 t 不用手动累加秒数,而是用“已过去的时间差”——rAF 回调参数 timestamp 提供高精度时间戳,可计算 Δt(帧间间隔),进而累加总时间 t。
- 初始化时记录起始时间
startTime = performance.now() - 每次 rAF 回调中:
const elapsed = (timestamp - startTime) / 1000;(转成秒) - 代入公式算出当前 x、y 坐标
封装动画逻辑,避免全局变量污染
把小球状态(位置、初速度、重力、起始时间)封装成对象或类,方便复用多个抛物线实例:
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
- 定义
Ball构造函数,接收x0, y0, vx, vy, gravity=9.8 - 添加
update(elapsed)方法:根据 elapsed 计算当前 x/y - 添加
render(ctx)方法:用 canvas 绘制或设置 DOM 元素 style.transform
用 requestAnimationFrame 驱动循环
rAF 不是“每秒60次固定节奏”,而是浏览器按屏幕刷新率调度,且会自动节流(如标签页隐藏时暂停)。正确写法是递归调用:
- 写一个
animate(timestamp)函数 - 首次调用前设
startTime = timestamp - 函数内先 update + render,再调用
requestAnimationFrame(animate) - 注意:不要在循环里反复 new Date() 或 performance.now(),直接用 rAF 传入的 timestamp
补充细节让运动更自然
纯公式容易显得“太理想”。加点现实感可提升体验:
- 水平方向加轻微空气阻力:每次更新
vx *= 0.999 - 落地后反弹:检测 y 超过画布底边时,翻转 vy 并乘以阻尼系数(如 0.8)
- 用
ctx.arc(x, y, radius, 0, Math.PI * 2)绘制小球,比 div 更轻量 - 若用 CSS 动画,建议改用
transform: translate(xpx, ypx),避免触发布局重排
不复杂但容易忽略:时间单位统一(秒)、坐标系 y 轴向下(所以重力加正号)、rAF 时间戳精度远高于 setInterval。写对这三点,抛物线就稳了。

















