用 Three.js 把宇宙装进浏览器,从地球到月球,从 ISS 到星辰大海——这不是静态模拟,是一个活着的宇宙。
前言
你有多久没好好看过星星了?
大多数人认识宇宙的方式,是教科书上的图表、NASA 发布的卫星照片、或者手机上的星图 App——它们很美,但总觉得隔着一层。
Atlas26 想做的是:把宇宙变成一个可以触摸的数字窗。
用 Next.js + Three.js + React Three Fiber 构建的实时 3D 太空可视化平台,通过 NASA 和 Celestrak 的实时数据,让行星、卫星、轨道都在你浏览器里活起来。
这不仅仅是一个 Demo,而是一个持续进化的"现代数字天文台"。

一、项目概览
GitHub:Abdul-Wasay-008/Atlas26
在线演示:https://atlas26.vercel.app
核心愿景
"What if space felt alive, beautiful, and emotionally engaging, not just educational?"
作者希望让太空不再只是冷冰冰的数据和图表,而是一个活着的、可感知的、有情感的宇宙。
二、Atlas26 能做什么?
2.1 实时地球可视化

地球不是一张贴图,而是一个动态球体:
- 昼夜交替渲染:基于真实太阳光方向计算晨昏线(terminator)
- 动态光照:太阳位置随时间变化,地球阴影实时更新
- 大气层效果:用 Shader 模拟地球大气散射
// 昼夜交替 Shader(示意)
varying vec3 vNormal;
varying vec3 vPosition;
uniform vec3 uSunDirection; // 太阳光方向
void main() {
vec3 viewDir = normalize(cameraPosition - vPosition);
float dotSun = max(dot(vNormal, uSunDirection), 0.0);
// 白天:反射太阳光 + 大气散射
// 黑夜:城市灯光 + 自发光
vec3 dayColor = texture2D(uDayTexture, vUv).rgb * dotSun;
vec3 nightColor = texture2D(uNightTexture, vUv).rgb * (1.0 - dotSun);
vec3 finalColor = mix(nightColor, dayColor, dotSun * 0.7);
gl_FragColor = vec4(finalColor, 1.0);
}
2.2 ISS 轨道追踪

国际空间站(ISS)不是静止的模型,而是基于真实轨道数据运行的:
- 轨道周期:约 90 分钟绕地球一圈
- 实时位置:根据时间计算轨道参数
- 可视化路径:绘制轨道轨迹,预测未来位置
// ISS 轨道计算(示意)
const issOrbit = {
inclination: 51.64, // 轨道倾角(度)
altitude: 408, // 轨道高度(km)
period: 92.68, // 轨道周期(分钟)
epoch: Date.now(), // 起始时间
};
function getISSPosition(time: number) {
const elapsed = (time - issOrbit.epoch) / 1000 / 60; // 分钟
const angle = (elapsed / issOrbit.period) * 2 * Math.PI;
// 简化的圆形轨道计算(实际需考虑偏心率等)
const radius = (EARTH_RADIUS + issOrbit.altitude) / 1000; // 单位转换
const x = radius * Math.cos(angle);
const z = radius * Math.sin(angle);
// 应用轨道倾角旋转
const y = z * Math.sin(issOrbit.inclination * DEG_TO_RAD);
return new Vector3(x, y, z * Math.cos(issOrbit.inclination * DEG_TO_RAD));
}
2.3 动态月相模拟

月球的位置、光照、阴影都是实时计算的:
- 月地距离:约 38.4 万公里(按比例缩放)
- 月相周期:约 29.5 天
- 光照方向:与太阳对齐,产生真实阴影
// 月相计算(示意)
function getMoonPhase(date: Date): number {
// 朔望月周期(天)
const SYNODIC_MONTH = 29.53;
// 已知新月日期
const KNOWN_NEW_MOON = new Date('2025-01-01');
const daysSinceNew = (date.getTime() - KNOWN_NEW_MOON.getTime()) / DAY_MS;
const phase = (daysSinceNew % SYNODIC_MONTH) / SYNODIC_MONTH;
return phase; // 0 = 新月, 0.5 = 满月, 1 = 下一个新月
}
2.4 电影级相机系统
相机不是简单的 OrbitControls,而是预定义的电影镜头路径:
// CameraControls.tsx
import { useFrame } from '@react-three/fiber';
import { useSpring } from '@react-spring/three';
const presets = {
earth: { position: [0, 0, 5], target: [0, 0, 0] },
moon: { position: [1, 0.5, 3], target: [0.5, 0, 1.5] },
iss: { position: [0.2, 0.3, 1], target: [0, 0, 0] },
};
function CameraControls({ currentPreset }) {
const { position, target } = useSpring({
position: presets[currentPreset].position,
target: presets[currentPreset].target,
config: { mass: 1, tension: 120, friction: 20 },
});
useFrame(({ camera }) => {
camera.position.lerp(new Vector3(...position.get()), 0.1);
camera.lookAt(new Vector3(...target.get()));
});
return null;
}
解析:
useSpring提供平滑的物理缓动(mass/tension/friction 模拟弹簧系统),相机在预设位置之间切换时,会自然地加速和减速,而不是生硬地跳变。
三、使用技巧
3.1 本地运行
# 克隆项目
git clone https://github.com/Abdul-Wasay-008/Atlas26.git
cd Atlas26
# 安装依赖
npm install
# 启动开发服务器
npm run dev
# 访问 http://localhost:3000
3.2 交互方式
| 操作 | 说明 |
|---|---|
| 鼠标拖拽 | 旋转视角 |
| 滚轮缩放 | 推拉相机 |
| 点击天体 | 查看详细信息面板 |
| UI 按钮 | 切换相机预设(地球/月球/ISS) |
3.3 自定义天体数据
项目支持本地元数据系统,你可以扩展新的天体:
// data/celestial-objects.ts
export const celestialObjects = {
earth: {
name: 'Earth',
radius: 6371, // km
mass: '5.97e24 kg',
texture: '/textures/earth.jpg',
orbitPeriod: 365.25, // days
rotationPeriod: 24, // hours
},
moon: {
name: 'Moon',
radius: 1737,
distance: 384400,
texture: '/textures/moon.jpg',
orbitPeriod: 27.3,
rotationPeriod: 27.3,
},
// 添加你自己的天体...
};
四、核心代码解读
4.1 项目架构
src/
├── components/
│ ├── Earth/ # 地球组件(昼夜渲染、大气)
│ ├── Moon/ # 月球组件(月相、阴影)
│ ├── ISS/ # 国际空间站(轨道追踪)
│ ├── Stars/ # 星空背景(粒子系统)
│ └── CameraControls/ # 电影级相机控制
├── hooks/
│ ├── useOrbitalData.ts # 轨道数据计算
│ ├── useSunPosition.ts # 太阳位置计算
│ └── useTimeScale.ts # 时间缩放控制
├── utils/
│ ├── orbit.ts # 轨道计算工具
│ └── celestial.ts # 天体常数(G、AU 等)
└── data/
└── celestial-objects.ts # 天体元数据
4.2 星空粒子系统
// Stars.tsx
import { Points, PointMaterial } from '@react-three/drei';
const COUNT = 10000;
const stars = Array.from({ length: COUNT }, () => ({
position: [
(Math.random() - 0.5) * 2000,
(Math.random() - 0.5) * 2000,
(Math.random() - 0.5) * 2000,
],
size: Math.random() * 2 + 0.5,
color: new Color().setHSL(Math.random(), 0.2, 0.8),
}));
function Stars() {
return (
<Points positions={stars.map(s => s.position)}>
<PointMaterial size={1} vertexColors sizeAttenuation />
</Points>
);
}
解析:
@react-three/drei的Points组件是 Three.jsBufferGeometry的 React 封装。一次性上传 10000 个顶点到 GPU,用gl.POINTS绘制,性能极高。sizeAttenuation让点的大小随距离衰减,符合透视规律。
4.3 太阳位置计算(基于时间)
// hooks/useSunPosition.ts
export function useSunPosition(date: Date) {
// 简化版:春分点方向 + 地球自转
const dayOfYear = getDayOfYear(date);
const declination = 23.45 * Math.sin((dayOfYear - 81) * DEG_TO_RAD);
const x = Math.cos(declination * DEG_TO_RAD);
const y = Math.sin(declination * DEG_TO_RAD);
const z = 0;
return new Vector3(x, y, z).normalize();
}
解析:太阳在地球坐标系中的位置受季节影响(赤纬角),约 ±23.45°(地球自转轴倾角)。这个简化计算忽略了岁差、章动等高阶项,对于可视化足够精确。
五、为什么这个项目值得关注?
5.1 诗意 × 技术

Atlas26 最打动人的地方在于它的情感表达——作者不是为了炫技而写代码,而是为了让人们"感觉"到宇宙的尺度与美。
这不是一个普通的技术 Demo,而是一个数字艺术作品。
5.2 实时数据驱动的 3D 可视化
很多 Three.js 项目使用静态模型和动画,而 Atlas26 直接对接 NASA & Celestrak 的实时轨道数据,让天体位置是"真"的。
这种数据驱动的思路,可以应用在任何需要实时可视化系统的场景:金融、交通、物流、物联网……
5.3 WebXR & AR 的前瞻布局
README 中已经列出了 WebXR 和 AR 的长期规划——这意味着未来你可以在 VR 头显里"走进"太空,或者用手机 AR 把月球放在你的桌子上。
浏览器 + 3D + 空间计算,这是未来十年的重要方向。
六、未来计划
| 时间范围 | 计划功能 |
|---|---|
| 近期 | NASA/Celestrak 实时数据、更准确的行星位置、改进光照和 Shader |
| 中期 | AI 驱动天体解释、教育模式、时间速度控制、多天体层(卫星/碎片/空间站) |
| 长期 | WebXR 沉浸式探索、AR 模式、叙事驱动的宇宙故事、多用户共享探索、虚拟课堂 |
七、结语
Atlas26 是一个有温度的项目。
作者把一个"太空可视化工具",升级成了一个"数字天文台"——它不只是展示数据,而是让人与宇宙产生情感连接。
如果你对 3D 可视化、数据驱动系统、天文科普、WebXR/AR 这些方向感兴趣,这个项目值得你深入研究。
