动态星系旋转的核心是用极坐标生成螺旋臂恒星分布、分层差速旋转(core/arms/halo不同角速度)、透明度与大小随半径和角速度渐变,并通过残影、鼠标拖拽缩放实现交互,无需物理引擎或WebGL。

用 Canvas 实现动态星系旋转,核心不是“画星星”,而是用路径动画模拟引力轨道+视觉层次+时间驱动的运动逻辑。关键在坐标变换、极坐标计算、透明度与缩放渐变,而非逐帧重绘整个星系。
用极坐标生成螺旋臂与恒星分布
真实星系(如银河系)恒星并非随机分布,而是沿对数螺旋臂聚集。Canvas 中不需物理引擎,只需数学映射:
- 对每个恒星,设定其属于第 N 条旋臂(如 2–4 条),再按角度 θ 和半径 r = a × ebθ 计算位置,其中 a、b 控制螺旋松紧
- 加入小范围随机偏移(±5px)和大小抖动(0.5–2px),避免机械感
- 用 ctx.beginPath() → ctx.arc(x, y, radius, 0, Math.PI * 2) 绘制单颗星,避免 stroke 轮廓,只 fill
分层旋转:中心黑洞 + 旋臂 + 外围晕轮
不同区域旋转角速度不同——这是星系差速旋转(differential rotation)的关键视觉特征:
- 定义三组恒星数组:core(r ≤ 30px)、arms(30px 200px)
- 每帧更新时,对每组应用独立角增量:coreSpeed = 0.015,armSpeed = 0.008,haloSpeed = 0.003(单位:弧度/帧)
- 用 ctx.save() → ctx.translate(centerX, centerY) → ctx.rotate(angle) → 绘制 → ctx.restore() 避免全局坐标混乱
添加动态视觉反馈:亮度衰减与运动模糊
纯色圆点无法体现远近与速度。通过 Canvas 2D API 模拟视觉深度:
立即学习“前端免费学习笔记(深入)”;
- 根据半径 r 设置 alpha 值:alpha = Math.max(0.1, 1 - r / 400),越外围越透明
- 根据角速度设置大小:size = Math.max(0.3, 1.5 - Math.abs(angularVelocity) * 100),高速旋转星体略缩小,增强动感
- 启用半透明叠加:在 requestAnimationFrame 开头不 clearRect,仅用 ctx.fillStyle = 'rgba(0,0,0,0.05)'; ctx.fillRect(0,0,width,height) 实现残影效果
交互增强:鼠标拖拽旋转 + 滚轮缩放
让星系可探索,不只是播放动画:
- 监听 mousedown/mousemove:记录起始角度,拖拽时动态调整整体 rotate 偏移量(globalRotationOffset)
- 监听 wheel 事件:缩放 canvas 的 transform(用 setTransform 重置,再 scale),同时调整视口中心 translate
- 为防卡顿,限制最大恒星数量(如 ≤ 3000 颗),超出时自动降低 halo 层密度
不需要 WebGL 或第三方库,纯 HTML5 Canvas + 数学建模就能做出有科学依据又具表现力的星系动画。重点是把天体力学简化为可计算的视觉规则,再用 Canvas 的状态管理高效渲染。



















