Cosmic 3D — 三维宇宙可视化
基于 Three.js 构建的沉浸式 3D 宇宙可视化——4000 粒子星空、多色星云、光环系统,交互式拖拽探索。
📋 项目概览
技术栈
Three.jsJavaScriptWebGLOrbitControls
功能特性
- Three.js 3D 场景:4000 粒子星空、星云、光环
- OrbitControls 交互:拖拽旋转、滚轮缩放
- 自动旋转 + 粒子动态漂移
- 纯前端,零外部依赖(除 Three.js CDN)
- 响应式:适配桌面和移动端
📖 技术分析报告在 GitHub 查看 ↗
Cosmic 3D — 三维宇宙可视化
项目概述
基于 Three.js 构建的沉浸式 3D 宇宙可视化。4000 粒子星空 + 多色星云 + 发光光环系统,支持拖拽旋转和滚轮缩放,自动旋转展示宇宙层次感。
技术栈
- Three.js r160 — WebGL 3D 渲染引擎
- OrbitControls — 相机轨道控制(拖拽旋转 + 自动旋转)
- 纯前端 — 单 HTML 文件,CDN 加载,零构建步骤
架构设计
┌─────────────────────┐
│ 场景 (Scene) │
│ background: #070714 │
└──────┬──────────────┘
│
┌──────────────┼──────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ 星空 │ │ 星云 │ │ 光环 │
│ 4000粒子 │ │ 3色星云 │ │ 3层光环 │
│ 球面分布 │ │ 粒子扩散 │ │ 自转动画 │
│ HSL着色 │ │ Additive │ │ 倾角旋转 │
└──────────┘ └──────────┘ └──────────┘
│
▼
┌──────────┐
│ Controls │
│ Orbit │
│ 阻尼+自转 │
└──────────┘
场景构成
| 元素 | 技术实现 | 参数 |
|---|---|---|
| 背景星空 | THREE.Points + BufferGeometry |
4000 粒子,半径 100-600 球面分布 |
| 粒子着色 | HSL 色相偏移(0.58-0.73),逐粒子随机 |
vertexColors 逐顶点颜色 |
| 星云 | 局部粒子聚集 + AdditiveBlending |
3 团:蓝/粉/紫,半透明叠加 |
| 光环 | 环形粒子分布 + 倾角旋转 | 3 层:半径 180/250/400,自转速度各异 |
| 交互 | OrbitControls |
阻尼 0.05,自动旋转 0.3 rad/s |
关键技术点
1. 粒子系统优化
4000 粒子使用 BufferGeometry 的 Float32Array 批量设置位置、颜色、大小属性,避免逐个创建几何体。使用 AdditiveBlending 实现发光效果。
2. 视觉层次
三层结构叠加:远处背景粒子(深蓝调)→ 中景星云(彩色扩散)→ 近景光环(高亮度),利用距离和透明度创造景深感。
3. 自动旋转与交互
OrbitControls.autoRotate 提供默认的宇宙自转效果,用户拖拽时自动暂停,松手后继续。
效果示意
首页顶部背景即为此宇宙可视化的简化版(Canvas 2D 实现,120 粒子 + 连线),完整版在演示页面。
🚀 在线演示新窗口打开 ↗
💻 核心代码Three.js · JavaScript · WebGL · OrbitControls
javascript场景搭建与星空粒子
Three.js 场景初始化 + 4000 粒子球面分布,实现深邃星空背景。
// ── Scene ──
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x070714);
// ── Camera ──
const camera = new THREE.PerspectiveCamera(70, innerWidth / innerHeight, 0.1, 3000);
camera.position.set(0, 0, 400);
// ── Renderer ──
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(innerWidth, innerHeight);
renderer.setPixelRatio(Math.min(devicePixelRatio, 2));
// ── Controls ──
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.autoRotate = true;
controls.autoRotateSpeed = 0.3;
// ── Main stars (sphere distribution) ──
const starGeo = new THREE.BufferGeometry();
const positions = new Float32Array(4000 * 3);
const colors = new Float32Array(4000 * 3);
const sizes = new Float32Array(4000);
for (let i = 0; i < 4000; i++) {
const theta = Math.random() * Math.PI * 2;
const phi = Math.acos(2 * Math.random() - 1);
const r = 100 + Math.random() * 500;
positions[i*3] = r * Math.sin(phi) * Math.cos(theta);
positions[i*3+1] = r * Math.cos(phi);
positions[i*3+2] = r * Math.sin(phi) * Math.sin(theta);
const c = new THREE.Color().setHSL(0.58 + Math.random() * 0.15, 0.6, 0.5 + Math.random() * 0.4);
colors[i*3] = c.r; colors[i*3+1] = c.g; colors[i*3+2] = c.b;
sizes[i] = 0.5 + Math.random() * 2;
}
starGeo.setAttribute('position', new THREE.BufferAttribute(positions, 3));
starGeo.setAttribute('color', new THREE.BufferAttribute(colors, 3));
starGeo.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
const starMat = new THREE.PointsMaterial({
size: 1.2, vertexColors: true, transparent: true,
opacity: 0.9, blending: THREE.AdditiveBlending, depthWrite: false,
});
const stars = new THREE.Points(starGeo, starMat);
scene.add(stars);javascript星云与光环系统
粒子星云生成函数 + 发光光环旋转动画,增强宇宙层次感。
// ── 星云生成 ──
function createNebula(pos, size, color, count) {
const geo = new THREE.BufferGeometry();
const p = new Float32Array(count * 3);
const c = new Float32Array(count * 3);
const base = new THREE.Color(color);
for (let i = 0; i < count; i++) {
const r = Math.random() * size;
const theta = Math.random() * Math.PI * 2;
const phi = Math.acos(2 * Math.random() - 1);
p[i*3] = pos[0] + r * Math.sin(phi) * Math.cos(theta);
p[i*3+1] = pos[1] + r * Math.cos(phi) * 0.3;
p[i*3+2] = pos[2] + r * Math.sin(phi) * Math.sin(theta);
const col = base.clone().lerp(new THREE.Color(0x000000), Math.random() * 0.7);
c[i*3] = col.r; c[i*3+1] = col.g; c[i*3+2] = col.b;
}
geo.setAttribute('position', new THREE.BufferAttribute(p, 3));
geo.setAttribute('color', new THREE.BufferAttribute(c, 3));
return new THREE.Points(geo, new THREE.PointsMaterial({
size: 3, vertexColors: true, transparent: true,
opacity: 0.3, blending: THREE.AdditiveBlending, depthWrite: false,
}));
}
// ── 光环生成 ──
function createRing(radius, colorY, tiltX, speed) {
const count = 2000;
const geo = new THREE.BufferGeometry();
const p = new Float32Array(count * 3);
for (let i = 0; i < count; i++) {
const angle = Math.random() * Math.PI * 2;
const r = radius + (Math.random() - 0.5) * 30;
p[i*3] = r * Math.cos(angle);
p[i*3+1] = (Math.random() - 0.5) * 4;
p[i*3+2] = r * Math.sin(angle);
}
geo.setAttribute('position', new THREE.BufferAttribute(p, 3));
return { mesh: new THREE.Points(geo, new THREE.PointsMaterial({
color: new THREE.Color().setHSL(colorY, 0.8, 0.5), size: 1.2,
transparent: true, opacity: 0.4, blending: THREE.AdditiveBlending,
})), speed, tiltX };
}
// 添加光环
const rings = [createRing(250, 0.5, 0.3, 0.0008),
createRing(400, 0.7, -0.5, -0.0005),
createRing(180, 0.3, 0.8, 0.0012)];
rings.forEach(r => { r.mesh.rotation.x = r.tiltX; scene.add(r.mesh); });📁 源文件清单GitHub 仓库 ↗
| 路径 | 说明 | 行数 |
|---|---|---|
public/demos/cosmic-3d/index.html | 完整 Three.js 宇宙可视化(183 行) | 183 |