用canvas实现星体引力运行需三步:先按牛顿定律计算矢量引力与加速度;再用欧拉或verlet积分更新位置速度;最后用canvas高效绘制星体及轨迹,注意缩放、防除零和初始条件。

用 Canvas 实现万有引力下的星体运行,核心是**物理建模 + 数值积分 + 绘图渲染**三步结合。不依赖第三方库,纯 JS 就能做出较真实的双星、行星绕恒星等效果,关键在于正确实现牛顿万有引力公式和稳定更新位置速度。
1. 万有引力模型:力与加速度的计算
根据牛顿万有引力定律:F = G × (m₁ × m₂) / r²,其中 G 是引力常量(可取 6.67430e-11,但 Canvas 场景中常缩放为 0.1~10 以适配像素尺度)。对每个星体:
- 遍历其他所有星体,计算作用在它身上的合力(矢量)
- 由 F = m × a 得出加速度 a = F / m,分解为 x、y 方向分量
- 注意:r 是两星体质心距离,需用勾股定理计算;方向单位向量 = (dx/r, dy/r)
2. 数值积分:用欧拉法或更稳的 Verlet 积分更新状态
Canvas 动画基于 requestAnimationFrame(约 60fps),每帧需更新位置和速度。简单场景可用显式欧拉法:
- 先用当前加速度更新速度:vₓ += aₓ × dt,v_y += a_y × dt
- 再用新速度更新位置:x += vₓ × dt,y += v_y × dt
- dt 取固定值(如 1/60),避免因帧率波动导致轨迹发散
若出现轨道漂移或能量不守恒,建议改用Velocity Verlet:先半步更新速度 → 全步更新位置 → 再半步更新速度,稳定性更好。
3. Canvas 渲染:高效绘制与轨迹保留
每次帧更新前,清空画布(ctx.clearRect(0, 0, width, height)),再逐个绘制:
- 星体:用 ctx.beginPath() + ctx.arc() + ctx.fill(),半径可正比于质量
- 轨迹线:为每个星体维护一个坐标点数组(如最多存 200 点),每帧 push 当前位置,再用 ctx.stroke() 连成路径
- 优化:轨迹点过多时,用 array.shift() 控制长度;星体不透明度略降可营造拖尾感
4. 实用技巧与避坑提示
真实模拟易卡顿或失稳,这些细节很关键:
- 质量与坐标缩放:天文尺度太大,把 1 AU ≈ 100 像素,太阳质量设为 1000,行星设为 1~10,G 调整到 0.5 左右效果更直观
- 避免除零:计算 r 时加极小偏移(如 r = Math.hypot(dx, dy) + 1e-8)防止星体重叠崩溃
- 初始条件决定轨道:圆形轨道需满足 v = √(G×M / r);给错初速会变成椭圆、抛物线甚至飞走
- 关闭抗锯齿:ctx.imageSmoothingEnabled = false 让小星体更锐利
不复杂但容易忽略——物理逻辑写对了,动画自然就“活”起来。从双星互绕开始调试,再加第三体,逐步验证力的叠加和数值稳定性。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










