3D太阳系 html 源码-拿走不谢
·
1、效果-支持鼠标互动

2、在线体验
3、源码
把下面内容保存到 txt,另存为 .html 格式,再使用浏览器打开即可
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>3D 太阳系 - Three.js</title>
<style>
body { margin: 0; overflow: hidden; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; }
#info {
position: absolute;
top: 20px;
left: 20px;
color: rgba(255,255,255,0.8);
background: rgba(0,0,0,0.5);
padding: 8px 16px;
border-radius: 20px;
pointer-events: none;
font-size: 14px;
backdrop-filter: blur(4px);
border: 1px solid rgba(255,255,255,0.1);
z-index: 100;
}
#controls-hint {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
color: rgba(255,255,255,0.4);
background: rgba(0,0,0,0.3);
padding: 6px 14px;
border-radius: 20px;
font-size: 12px;
backdrop-filter: blur(2px);
border: 1px solid rgba(255,255,255,0.05);
pointer-events: none;
z-index: 100;
}
</style>
</head>
<body>
<div id="info">🌞 太阳系 3D · 鼠标拖动/滚轮</div>
<div id="controls-hint">行星公转 · 自转 · 光照</div>
<!-- 引入 Three.js 核心库和扩展 -->
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.128.0/build/three.module.js",
"three/addons/": "https://unpkg.com/three@0.128.0/examples/jsm/"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { CSS2DRenderer, CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js';
// --- 初始化场景、相机、渲染器 ---
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x050510); // 深空色
// 透视相机
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 30, 60);
camera.lookAt(0, 0, 0);
// WebGL渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = false; // 为了性能,不开启阴影(行星阴影对效果影响不大)
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
document.body.appendChild(renderer.domElement);
// CSS2渲染器用于文字标签
const labelRenderer = new CSS2DRenderer();
labelRenderer.setSize(window.innerWidth, window.innerHeight);
labelRenderer.domElement.style.position = 'absolute';
labelRenderer.domElement.style.top = '0px';
labelRenderer.domElement.style.left = '0px';
labelRenderer.domElement.style.pointerEvents = 'none'; // 让标签不干扰鼠标操作
document.body.appendChild(labelRenderer.domElement);
// 轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.autoRotate = false;
controls.enableZoom = true;
controls.target.set(0, 0, 0);
controls.maxPolarAngle = Math.PI / 2;
controls.minDistance = 10;
controls.maxDistance = 150;
// --- 光照 ---
// 环境光提供基础照明
const ambientLight = new THREE.AmbientLight(0x404060);
scene.add(ambientLight);
// 太阳本身作为点光源
const sunLight = new THREE.PointLight(0xffeedd, 2, 0, 0);
sunLight.position.set(0, 0, 0);
scene.add(sunLight);
// 辅助照亮行星的正面
const fillLight = new THREE.DirectionalLight(0xffffff, 0.5);
fillLight.position.set(1, 1, 1);
scene.add(fillLight);
// 背面补光
const backLight = new THREE.DirectionalLight(0x446688, 0.3);
backLight.position.set(-1, -0.5, -1);
scene.add(backLight);
// --- 星空背景 (粒子系统) ---
const starsGeometry = new THREE.BufferGeometry();
const starsCount = 4000;
const starsPositions = new Float32Array(starsCount * 3);
for (let i = 0; i < starsCount * 3; i += 3) {
// 分布在半径 200-500 的球壳内
const radius = 200 + Math.random() * 300;
const theta = Math.random() * Math.PI * 2;
const phi = Math.acos((Math.random() * 2) - 1);
starsPositions[i] = radius * Math.sin(phi) * Math.cos(theta);
starsPositions[i+1] = radius * Math.sin(phi) * Math.sin(theta);
starsPositions[i+2] = radius * Math.cos(phi);
}
starsGeometry.setAttribute('position', new THREE.BufferAttribute(starsPositions, 3));
const starsMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 0.35,
transparent: true,
opacity: 0.9,
blending: THREE.AdditiveBlending
});
const stars = new THREE.Points(starsGeometry, starsMaterial);
scene.add(stars);
// 额外小星星(更远更暗)
const starsGeometry2 = new THREE.BufferGeometry();
const starsCount2 = 2000;
const starsPositions2 = new Float32Array(starsCount2 * 3);
for (let i = 0; i < starsCount2 * 3; i += 3) {
const radius = 500 + Math.random() * 400;
const theta = Math.random() * Math.PI * 2;
const phi = Math.acos((Math.random() * 2) - 1);
starsPositions2[i] = radius * Math.sin(phi) * Math.cos(theta);
starsPositions2[i+1] = radius * Math.sin(phi) * Math.sin(theta);
starsPositions2[i+2] = radius * Math.cos(phi);
}
starsGeometry2.setAttribute('position', new THREE.BufferAttribute(starsPositions2, 3));
const starsMaterial2 = new THREE.PointsMaterial({
color: 0x88aaff,
size: 0.2,
transparent: true,
opacity: 0.5,
blending: THREE.AdditiveBlending
});
const stars2 = new THREE.Points(starsGeometry2, starsMaterial2);
scene.add(stars2);
// --- 辅助对象:轨道线 ---
function createOrbit(radius, color = 0x446688) {
const points = [];
const segments = 64;
for (let i = 0; i <= segments; i++) {
const angle = (i / segments) * Math.PI * 2;
points.push(new THREE.Vector3(radius * Math.cos(angle), 0, radius * Math.sin(angle)));
}
const geometry = new THREE.BufferGeometry().setFromPoints(points);
const material = new THREE.LineBasicMaterial({ color: color, transparent: true, opacity: 0.25 });
const orbitLine = new THREE.Line(geometry, material);
return orbitLine;
}
// 行星数据:名称, 颜色, 大小(半径比例), 轨道半径, 公转速度, 自转速度
// 为了视觉效果,大小和距离做了非等比调整
const planetsData = [
{ name: '水星', color: 0xaaaaaa, size: 0.4, distance: 5, speed: 0.02, rotationSpeed: 0.004 },
{ name: '金星', color: 0xffcc88, size: 0.6, distance: 7, speed: 0.015, rotationSpeed: 0.002 },
{ name: '地球', color: 0x4488ff, size: 0.7, distance: 9, speed: 0.012, rotationSpeed: 0.006 },
{ name: '火星', color: 0xff6633, size: 0.5, distance: 11, speed: 0.01, rotationSpeed: 0.005 },
{ name: '木星', color: 0xddbb99, size: 1.4, distance: 15, speed: 0.007, rotationSpeed: 0.009 },
{ name: '土星', color: 0xeeddbb, size: 1.2, distance: 19, speed: 0.005, rotationSpeed: 0.007, hasRing: true },
{ name: '天王星', color: 0x88ccff, size: 0.9, distance: 23, speed: 0.004, rotationSpeed: 0.003 },
{ name: '海王星', color: 0x3366aa, size: 0.9, distance: 27, speed: 0.003, rotationSpeed: 0.003 }
];
// 存储行星对象以便动画更新
const planets = [];
// --- 创建太阳 (发光) ---
const sunGeometry = new THREE.SphereGeometry(2.5, 32, 32);
const sunMaterial = new THREE.MeshStandardMaterial({
color: 0xffaa44,
emissive: 0xff5500,
emissiveIntensity: 1.2,
roughness: 0.4,
});
const sun = new THREE.Mesh(sunGeometry, sunMaterial);
scene.add(sun);
// 太阳光晕 (粒子环)
const glowParticlesGeo = new THREE.BufferGeometry();
const glowCount = 800;
const glowPos = new Float32Array(glowCount * 3);
for (let i = 0; i < glowCount; i++) {
const radius = 2.8 + Math.random() * 1.2;
const theta = Math.random() * Math.PI * 2;
const phi = Math.acos((Math.random() * 2) - 1);
glowPos[i*3] = radius * Math.sin(phi) * Math.cos(theta);
glowPos[i*3+1] = radius * Math.sin(phi) * Math.sin(theta);
glowPos[i*3+2] = radius * Math.cos(phi);
}
glowParticlesGeo.setAttribute('position', new THREE.BufferAttribute(glowPos, 3));
const glowParticlesMat = new THREE.PointsMaterial({
color: 0xffaa33,
size: 0.08,
transparent: true,
blending: THREE.AdditiveBlending,
depthWrite: false
});
const glowParticles = new THREE.Points(glowParticlesGeo, glowParticlesMat);
scene.add(glowParticles);
// 太阳标签
const sunLabelDiv = document.createElement('div');
sunLabelDiv.textContent = '☀️ 太阳';
sunLabelDiv.style.color = '#ffaa44';
sunLabelDiv.style.fontSize = '18px';
sunLabelDiv.style.fontWeight = 'bold';
sunLabelDiv.style.textShadow = '0 0 20px rgba(255,100,0,0.8)';
const sunLabel = new CSS2DObject(sunLabelDiv);
sunLabel.position.set(0, 3.5, 0);
scene.add(sunLabel);
// --- 创建行星及其轨道 ---
planetsData.forEach((data, index) => {
// 轨道
const orbitColor = 0x88aacc;
const orbit = createOrbit(data.distance, orbitColor);
scene.add(orbit);
// 行星本体
const geometry = new THREE.SphereGeometry(data.size, 32, 32);
const material = new THREE.MeshStandardMaterial({
color: data.color,
roughness: 0.5,
metalness: 0.1,
emissive: new THREE.Color(data.color).multiplyScalar(0.1)
});
const planet = new THREE.Mesh(geometry, material);
planet.castShadow = false;
planet.receiveShadow = false;
// 随机初始角度
const initAngle = Math.random() * Math.PI * 2;
planet.position.x = data.distance * Math.cos(initAngle);
planet.position.z = data.distance * Math.sin(initAngle);
scene.add(planet);
// 如果是土星,添加光环
if (data.hasRing) {
const ringGeometry = new THREE.RingGeometry(data.size * 1.4, data.size * 2.2, 64);
const ringMaterial = new THREE.MeshStandardMaterial({
color: 0xccbb99,
side: THREE.DoubleSide,
transparent: true,
opacity: 0.6,
roughness: 0.7
});
const ring = new THREE.Mesh(ringGeometry, ringMaterial);
ring.rotation.x = Math.PI / 2.2; // 倾斜
ring.rotation.z = 0.3;
planet.add(ring); // 添加到行星,随行星移动
}
// 行星标签
const labelDiv = document.createElement('div');
labelDiv.textContent = data.name;
labelDiv.style.color = '#ddd';
labelDiv.style.fontSize = '14px';
labelDiv.style.fontWeight = '300';
labelDiv.style.textShadow = '0 0 10px rgba(0,0,0,0.8)';
labelDiv.style.background = 'rgba(0,0,0,0.4)';
labelDiv.style.padding = '2px 8px';
labelDiv.style.borderRadius = '12px';
labelDiv.style.border = '1px solid rgba(255,255,255,0.1)';
labelDiv.style.backdropFilter = 'blur(2px)';
const label = new CSS2DObject(labelDiv);
label.position.set(0, data.size + 0.6, 0);
planet.add(label);
// 保存行星数据用于动画
planets.push({
mesh: planet,
distance: data.distance,
speed: data.speed,
rotationSpeed: data.rotationSpeed,
angle: initAngle
});
});
// 添加一些随机的小行星带(装饰)
const asteroidBeltGeometry = new THREE.BufferGeometry();
const asteroidCount = 2000;
const asteroidPositions = new Float32Array(asteroidCount * 3);
for (let i = 0; i < asteroidCount * 3; i += 3) {
const radius = 13 + Math.random() * 1.5;
const angle = Math.random() * Math.PI * 2;
const yOffset = (Math.random() - 0.5) * 0.8;
asteroidPositions[i] = radius * Math.cos(angle);
asteroidPositions[i+1] = yOffset;
asteroidPositions[i+2] = radius * Math.sin(angle);
}
asteroidBeltGeometry.setAttribute('position', new THREE.BufferAttribute(asteroidPositions, 3));
const asteroidMaterial = new THREE.PointsMaterial({
color: 0xccaa88,
size: 0.08,
transparent: true,
opacity: 0.6
});
const asteroidBelt = new THREE.Points(asteroidBeltGeometry, asteroidMaterial);
scene.add(asteroidBelt);
// 再添加一些更远的柯伊伯带装饰
const outerBeltGeometry = new THREE.BufferGeometry();
const outerCount = 1500;
const outerPositions = new Float32Array(outerCount * 3);
for (let i = 0; i < outerCount * 3; i += 3) {
const radius = 30 + Math.random() * 4;
const angle = Math.random() * Math.PI * 2;
const yOffset = (Math.random() - 0.5) * 1.5;
outerPositions[i] = radius * Math.cos(angle);
outerPositions[i+1] = yOffset;
outerPositions[i+2] = radius * Math.sin(angle);
}
outerBeltGeometry.setAttribute('position', new THREE.BufferAttribute(outerPositions, 3));
const outerMaterial = new THREE.PointsMaterial({
color: 0x88aadd,
size: 0.1,
transparent: true,
opacity: 0.3
});
const outerBelt = new THREE.Points(outerBeltGeometry, outerMaterial);
scene.add(outerBelt);
// --- 动画循环 ---
let clock = new THREE.Clock();
function animate() {
const delta = clock.getDelta();
const elapsedTime = performance.now() / 1000; // seconds
// 更新行星位置 (公转)
planets.forEach(p => {
p.angle += p.speed * delta * 8; // 乘系数调整速度
p.mesh.position.x = p.distance * Math.cos(p.angle);
p.mesh.position.z = p.distance * Math.sin(p.angle);
// 自转
p.mesh.rotation.y += p.rotationSpeed * delta * 20;
});
// 太阳自转
sun.rotation.y += 0.002 * delta * 20;
glowParticles.rotation.y += 0.0005 * delta * 20;
// 小行星带缓慢旋转
asteroidBelt.rotation.y += 0.001 * delta * 20;
outerBelt.rotation.y -= 0.0005 * delta * 20;
// 星星缓慢旋转
stars.rotation.y += 0.0001 * delta * 20;
stars2.rotation.x += 0.00005 * delta * 20;
// 更新控制器
controls.update();
// 渲染
renderer.render(scene, camera);
labelRenderer.render(scene, camera);
requestAnimationFrame(animate);
}
animate();
// --- 窗口自适应 ---
window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
labelRenderer.setSize(window.innerWidth, window.innerHeight);
}
// 提示用户操作
console.log('3D 太阳系已启动!');
</script>
</body>
</html>
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)