
生成3d的太阳系
Prompt
生成3d的太阳系
A system prompt was added to support web rendering
```html <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>3D 太阳系</title> <style> body { margin: 0; overflow: hidden; background: #000; } #loading { position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%); font: 18px/1.4 sans-serif; color: #fff; pointer-events: none; } </style> <!-- Three.js --> <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> <!-- OrbitControls --> <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/controls/OrbitControls.min.js"></script> </head> <body> <div id="loading">正在加载 3D 太阳系…</div> <script> /* ---------- 基础设置 ---------- */ const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 0.1, 2000); camera.position.set(0, 50, 120); const renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(innerWidth, innerHeight); renderer.setPixelRatio(devicePixelRatio); document.body.appendChild(renderer.domElement); const controls = new THREE.OrbitControls(camera, renderer.domElement); controls.enableDamping = true; /* ---------- 灯光 ---------- */ const ambient = new THREE.AmbientLight(0x222222); scene.add(ambient); const sunLight = new THREE.PointLight(0xffffff, 2, 0); sunLight.position.set(0, 0, 0); scene.add(sunLight); /* ---------- 星星背景 ---------- */ function createStarField() { const starsGeom = new THREE.BufferGeometry(); const starCount = 2000; const positions = new Float32Array(starCount * 3); for (let i = 0; i < starCount; i++) { const r = 800; const theta = Math.random() * 2 * Math.PI; const phi = Math.acos(2 * Math.random() - 1); positions[i * 3] = r * Math.sin(phi) * Math.cos(theta); positions[i * 3 + 1] = r * Math.sin(phi) * Math.sin(theta); positions[i * 3 + 2] = r * Math.cos(phi); } starsGeom.setAttribute('position', new THREE.BufferAttribute(positions, 3)); const starsMat = new THREE.PointsMaterial({ color: 0xffffff, size: 1 }); const starField = new THREE.Points(starsGeom, starsMat); scene.add(starField); } createStarField(); /* ---------- 天体材质 ---------- */ const textureLoader = new THREE.TextureLoader(); const textures = { sun: textureLoader.load('https://threejsfundamentals.org/threejs/resources/images/sun.jpg'), mercury:textureLoader.load('https://threejsfundamentals.org/threejs/resources/images/planets/mercury.jpg'), venus: textureLoader.load('https://threejsfundamentals.org/threejs/resources/images/planets/venus.jpg'), earth: textureLoader.load('https://threejsfundamentals.org/threejs/resources/images/planets/earth_atmos_2048.jpg'), mars: textureLoader.load('https://threejsfundamentals.org/threejs/resources/images/planets/mars.jpg'), jupiter:textureLoader.load('https://threejsfundamentals.org/threejs/resources/images/planets/jupiter.jpg'), saturn: textureLoader.load('https://threejsfundamentals.org/threejs/resources/images/planets/saturn.jpg'), saturnRing: textureLoader.load('https://threejsfundamentals.org/threejs/resources/images/planets/saturnringcolor.jpg'), }; /* ---------- 太阳 ---------- */ const sunGeo = new THREE.SphereGeometry(5, 32, 32); const sunMat = new THREE.MeshBasicMaterial({ map: textures.sun }); const sunMesh = new THREE.Mesh(sunGeo, sunMat); scene.add(sunMesh); /* ---------- 行星数据 ---------- */ const planetData = [ { name: "Mercury", radius: 0.38, distance: 10, speed: 0.04, tex: textures.mercury }, { name: "Venus", radius: 0.95, distance: 14, speed: 0.015, tex: textures.venus }, { name: "Earth", radius: 1.00, distance: 18, speed: 0.01, tex: textures.earth }, { name: "Mars", radius: 0.53, distance: 22, speed: 0.008, tex: textures.mars }, { name: "Jupiter", radius: 2.40, distance: 30, speed: 0.004, tex: textures.jupiter }, { name: "Saturn", radius: 2.00, distance: 38, speed: 0.003, tex: textures.saturn }, ]; /* ---------- 创建行星 ---------- */ const planets = []; planetData.forEach(data => { const orbit = new THREE.Object3D(); scene.add(orbit); const geometry = new THREE.SphereGeometry(data.radius, 32, 32); const material = new THREE.MeshStandardMaterial({ map: data.tex }); const mesh = new THREE.Mesh(geometry, material); mesh.position.x = data.distance; orbit.add(mesh); /* 土星环 */ if (data.name === 'Saturn') { const ringGeo = new THREE.RingGeometry(data.radius * 1.2, data.radius * 2, 64); const ringMat = new THREE.MeshBasicMaterial({ map: textures.saturnRing, side: THREE.DoubleSide, transparent: true }); const ring = new THREE.Mesh(ringGeo, ringMat); ring.rotation.x = Math.PI / 2.2; mesh.add(ring); } planets.push({ orbit, mesh, speed: data.speed }); }); /* ---------- 轨道可视化 ---------- */ const orbitMaterial = new THREE.LineBasicMaterial({ color: 0x444444 }); planetData.forEach(data => { const segments = 128, radius = data.distance; const orbitGeometry = new THREE.BufferGeometry(); const positions = []; for (let i = 0; i <= segments; i++) { const theta = (i / segments) * Math.PI * 2; positions.push(Math.cos(theta) * radius, 0, Math.sin(theta) * radius); } orbitGeometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3)); const line = new THREE.Line(orbitGeometry, orbitMaterial); scene.add(line); }); /* ---------- 动画循环 ---------- */ function animate() { requestAnimationFrame(animate); sunMesh.rotation.y += 0.001; // 太阳自转 planets.forEach(planet => { planet.orbit.rotation.y += planet.speed; planet.mesh.rotation.y += 0.02; // 行星自转 }); controls.update(); renderer.render(scene, camera); } animate(); /* ---------- 自适应窗口 ---------- */ addEventListener('resize', () => { camera.aspect = innerWidth / innerHeight; camera.updateProjectionMatrix(); renderer.setSize(innerWidth, innerHeight); }); /* ---------- 隐藏加载提示 ---------- */ window.addEventListener('load', () => { document.getElementById('loading').style.display = 'none'; }); </script> </body> </html> ```
Drag to resize
好的,这是一个使用 Three.js 库创建的可交互的3D太阳系模型。 您可以拖动鼠标来旋转视角,滚动鼠标滚轮来缩放。所有的代码都包含在一个HTML文件中,包括所需的JavaScript库。 ```html <!DOCTYPE html> <html lang="zh-CN"> <head> <title>3D 太阳系</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> <style> body { margin: 0; overflow: hidden; background-color: #000; } canvas { display: block; } </style> </head> <body> <script type="importmap"> { "imports": { "three": "https://unpkg.com/three@0.160.0/build/three.module.js", "three/addons/": "https://unpkg.com/three@0.160.0/examples/jsm/" } } </script> <script type="module"> import * as THREE from 'three'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; // 场景、相机和渲染器设置 const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000); camera.position.set(-90, 140, 140); const renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); // 轨道控制器 const controls = new OrbitControls(camera, renderer.domElement); controls.enableDamping = true; controls.minDistance = 20; controls.maxDistance = 1000; // 光源 const pointLight = new THREE.PointLight(0xFFFFFF, 3, 300); scene.add(pointLight); const ambientLight = new THREE.AmbientLight(0x333333); scene.add(ambientLight); // 纹理加载器 const textureLoader = new THREE.TextureLoader(); // 创建星空背景 const starGeometry = new THREE.SphereGeometry(1000, 64, 64); const starMaterial = new THREE.MeshBasicMaterial({ map: textureLoader.load('https://raw.githubusercontent.com/mrdoob/three.js/master/examples/textures/starry-night-sky.jpg'), side: THREE.BackSide }); const starMesh = new THREE.Mesh(starGeometry, starMaterial); scene.add(starMesh); // 创建太阳 const sunGeometry = new THREE.SphereGeometry(16, 30, 30); const sunMaterial = new THREE.MeshBasicMaterial({ map: textureLoader.load('https://raw.githubusercontent.com/mrdoob/three.js/master/examples/textures/planets/sun.jpg') }); const sun = new THREE.Mesh(sunGeometry, sunMaterial); scene.add(sun); // 行星数据 const planetsData = [ { name: '水星', size: 3.2, texture: 'mercury.jpg', distance: 28, speed: 4.7, rotationSpeed: 0.04 }, { name: '金星', size: 5.8, texture: 'venus_surface.jpg', distance: 44, speed: 3.5, rotationSpeed: 0.02 }, { name: '地球', size: 6, texture: 'earth_daymap.jpg', distance: 62, speed: 2.9, rotationSpeed: 0.2 }, { name: '火星', size: 4, texture: 'mars.jpg', distance: 78, speed: 2.4, rotationSpeed: 0.18 }, { name: '木星', size: 12, texture: 'jupiter.jpg', distance: 100, speed: 1.3, rotationSpeed: 0.4 }, { name: '土星', size: 10, texture: 'saturn.jpg', distance: 138, speed: 0.9, rotationSpeed: 0.38, hasRing: true, ringTexture: 'saturn_ring.png' }, { name: '天王星', size: 7, texture: 'uranus.jpg', distance: 176, speed: 0.6, rotationSpeed: 0.3 }, { name: '海王星', size: 7, texture: 'neptune.jpg', distance: 200, speed: 0.5, rotationSpeed: 0.32 } ]; const planetMeshes = []; // 创建行星的函数 function createPlanet(data) { const planetGeo = new THREE.SphereGeometry(data.size, 30, 30); const planetMat = new THREE.MeshStandardMaterial({ map: textureLoader.load(`https://raw.githubusercontent.com/mrdoob/three.js/master/examples/textures/planets/${data.texture}`) }); const planet = new THREE.Mesh(planetGeo, planetMat); // 创建轨道 const orbitGeometry = new THREE.RingGeometry(data.distance - 0.1, data.distance + 0.1, 128); const orbitMaterial = new THREE.MeshBasicMaterial({ color: 0x333333, side: THREE.DoubleSide }); const orbit = new THREE.Mesh(orbitGeometry, orbitMaterial); orbit.rotation.x = -Math.PI / 2; scene.add(orbit); // 创建一个Object3D作为行星的轨道中心 const obj = new THREE.Object3D(); obj.add(planet); if (data.hasRing) { const ringGeo = new THREE.RingGeometry(data.size + 2, data.size + 10, 64); const ringMat = new THREE.MeshBasicMaterial({ map: textureLoader.load(`https://raw.githubusercontent.com/mrdoob/three.js/master/examples/textures/planets/${data.ringTexture}`), side: THREE.DoubleSide, transparent: true }); const ring = new THREE.Mesh(ringGeo, ringMat); ring.rotation.x = -0.5 * Math.PI; planet.add(ring); } // 添加地球的月亮 if (data.name === '地球') { const moonGeo = new THREE.SphereGeometry(0.8, 30, 30); const moonMat = new THREE.MeshStandardMaterial({ map: textureLoader.load('https://raw.githubusercontent.com/mrdoob/three.js/master/examples/textures/planets/moon_1024.jpg') }); const moon = new THREE.Mesh(moonGeo, moonMat); const moonObj = new THREE.Object3D(); moon.position.x = 10; moonObj.add(moon); planet.add(moonObj); data.moonObj = moonObj; // 保存月球轨道对象以便动画 } planet.position.x = data.distance; scene.add(obj); data.mesh = planet; data.orbitObj = obj; return data; } planetsData.forEach(pData => planetMeshes.push(createPlanet(pData))); // 动画循环 function animate() { // 自转 sun.rotation.y += 0.004; planetMeshes.forEach(p => { p.mesh.rotation.y += p.rotationSpeed / 10; // 行星自转 p.orbitObj.rotation.y += p.speed / 100; // 行星公转 // 月球绕地球转 if (p.name === '地球') { p.moonObj.rotation.y += 0.05; } }); // 必需的更新 controls.update(); renderer.render(scene, camera); requestAnimationFrame(animate); } animate(); // 窗口大小调整处理 window.addEventListener('resize', () => { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); }); </script> </body> </html> ```
Drag to resize
```html <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>3D太阳系演示</title> <style> body { margin: 0; background: #000; overflow: hidden; } #info { position: absolute; top: 10px; left: 10px; color: #fff; background: rgba(0,0,0,0.6); padding: 8px 16px; border-radius: 8px; font-family: sans-serif; z-index:10; font-size: 15px; } </style> <script src="https://cdn.jsdelivr.net/npm/three@0.155.0/build/three.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/three@0.155.0/examples/js/controls/OrbitControls.min.js"></script> </head> <body> <div id="info">3D太阳系(可拖拽旋转,滚轮缩放)</div> <script> // 创建场景 const scene = new THREE.Scene(); scene.background = new THREE.Color(0x000000); // 创建相机 const camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.1, 2000); camera.position.set(0, 120, 250); // 渲染器 const renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); // 控制器 const controls = new THREE.OrbitControls(camera, renderer.domElement); // 恒星: 太阳 const sunGeometry = new THREE.SphereGeometry(20, 48, 48); const sunMaterial = new THREE.MeshBasicMaterial({ color: 0xffcc33 }); const sun = new THREE.Mesh(sunGeometry, sunMaterial); scene.add(sun); // 自发光 sunMaterial.emissive = new THREE.Color(0xffea80); sunMaterial.emissiveIntensity = 1.2; // 环境光和点光源 const ambient = new THREE.AmbientLight(0xffffff, 0.3); scene.add(ambient); const sunLight = new THREE.PointLight(0xffffff, 2, 1000); sunLight.position.copy(sun.position); scene.add(sunLight); // 行星参数 (半径, 距离, 颜色, 公转周期, 自转周期) // 行星列表: Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune const planets = [ { name: "水星", radius:1.6, dist: 30, color:0xc2b280, orbitalPeriod: 88, rotationPeriod: 58 }, { name: "金星", radius:4, dist: 41, color:0xeccc96, orbitalPeriod: 225, rotationPeriod: -243 }, { name: "地球", radius:4.4, dist: 56, color:0x4b86fb, orbitalPeriod: 365, rotationPeriod: 1 }, { name: "火星", radius:3.3, dist: 70, color:0xcc6e3b, orbitalPeriod: 687, rotationPeriod: 1 }, { name: "木星", radius:10, dist: 95, color:0xefefbb, orbitalPeriod: 4333, rotationPeriod: 0.4 }, { name: "土星", radius:8.7, dist: 120, color:0xf5e3b3, orbitalPeriod: 10759, rotationPeriod: 0.45 }, { name: "天王星", radius:6.2, dist: 145, color:0x81c8d6, orbitalPeriod: 30687, rotationPeriod: -0.72 }, { name: "海王星", radius:6.0, dist: 165, color:0x4976c6, orbitalPeriod: 60190, rotationPeriod: 0.67 } ]; // 行星、轨道对象数组 const planetMeshes = []; const orbitLines = []; // 创建行星和轨道 for (let i = 0; i < planets.length; i++) { const { name, radius, dist, color } = planets[i]; // 行星 const geometry = new THREE.SphereGeometry(radius, 32, 32); const material = new THREE.MeshPhongMaterial({ color: color }); const mesh = new THREE.Mesh(geometry, material); mesh.position.set(dist, 0, 0); scene.add(mesh); planetMeshes.push(mesh); // 轨道(环形线段) const orbitSegs = 128; const orbitGeometry = new THREE.BufferGeometry(); const positions = []; for (let j = 0; j < orbitSegs; j++) { const theta = (j / orbitSegs) * 2 * Math.PI; positions.push( Math.cos(theta) * dist, 0, Math.sin(theta) * dist ); } positions.push(positions[0], positions[1], positions[2]); orbitGeometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3)); const orbitMaterial = new THREE.LineBasicMaterial({ color: 0xffffff, opacity:0.3, transparent:true }); const orbitLine = new THREE.Line(orbitGeometry, orbitMaterial); scene.add(orbitLine); orbitLines.push(orbitLine); // 土星环 if (name === '土星') { const ringGeometry = new THREE.RingGeometry(radius + 2, radius + 7, 64); const ringMaterial = new THREE.MeshPhongMaterial({ color: 0xd2c292, side: THREE.DoubleSide, transparent: true, opacity: 0.55 }); const ring = new THREE.Mesh(ringGeometry, ringMaterial); ring.rotation.x = Math.PI / 2; mesh.add(ring); } } // 地球的简易月球 const moonRadius = 1.2; const moonDist = 8; const moonGeometry = new THREE.SphereGeometry(moonRadius, 24, 24); const moonMaterial = new THREE.MeshPhongMaterial({ color: 0xdddddd }); const moon = new THREE.Mesh(moonGeometry, moonMaterial); planetMeshes[2].add(moon); // 地球 moon.position.set(moonDist, 0, 0); // 动画 function animate() { requestAnimationFrame(animate); const time = Date.now() * 0.0005; for (let i = 0; i < planets.length; i++) { const planet = planets[i]; if (planet.orbitalPeriod!==0){ // 光速快进,加速10000倍 const angle = (time / planet.orbitalPeriod) * 2 * Math.PI * 10000; planetMeshes[i].position.x = Math.cos(angle) * planet.dist; planetMeshes[i].position.z = Math.sin(angle) * planet.dist; planetMeshes[i].rotation.y += 0.03 / Math.abs(planet.rotationPeriod); } } // 地球自转、月球公转 planetMeshes[2].rotation.y += 0.05; // 地球 moon.position.x = Math.cos(time * 15) * moonDist; moon.position.z = Math.sin(time * 15) * moonDist; renderer.render(scene, camera); controls.update(); } animate(); // 适应窗口 window.addEventListener('resize', () => { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); }); </script> </body> </html> ```
Drag to resize
下面是一个使用 Three.js 构建的简化版太阳系模型。这个模型包括了太阳、几个行星、围绕太阳的轨道,并且可以旋转镜头角度进行交互。 你可以直接运行以下 HTML 代码来查看效果: ```html <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <title>3D太阳系</title> <style> body { margin: 0; background: #000; overflow: hidden; } #info { position: absolute; top: 10px; width: 100%; text-align: center; color: white; font-family: sans-serif; } </style> </head> <body> <div id="info">3D太阳系模型</div> <script src="https://cdn.jsdelivr.net/npm/three@0.155.0/build/three.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/three@0.155.0/examples/js/controls/OrbitControls.min.js"></script> <script> let scene, camera, renderer, controls; let planets = []; init(); animate(); function init() { scene = new THREE.Scene(); // 相机设置 camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000); camera.position.set(0, 100, 200); // 渲染器 renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); // 光源 const ambientLight = new THREE.AmbientLight(0xaaaaaa); // 环境光 scene.add(ambientLight); const sunLight = new THREE.PointLight(0xffffff, 2, 0, 2); scene.add(sunLight); // 中心光源(太阳) // 轨道控制 controls = new THREE.OrbitControls(camera, renderer.domElement); controls.enableDamping = true; // 太阳 const sunGeometry = new THREE.SphereGeometry(10, 32, 32); const sunMaterial = new THREE.MeshBasicMaterial({ color: 0xffdd66 }); const sun = new THREE.Mesh(sunGeometry, sunMaterial); scene.add(sun); // 行星参数(名称, 颜色, 大小, 轨道半径, 速度) const planetList = [ { name: '水星', color: '0xaaaaaa', size: 1, orbit: 20, speed: 0.04 }, { name: '金星', color: '0xffcccc', size: 1.5, orbit: 30, speed: 0.03 }, { name: '地球', color: '0x3399ff', size: 1.8, orbit: 45, speed: 0.02 }, { name: '火星', color: '0xff3333', size: 1.3, orbit: 60, speed: 0.015 }, { name: '木星', color: '0xffcc66', size: 4, orbit: 90, speed: 0.01 }, { name: '土星', color: '0xffddaa', size: 3.5, orbit: 120, speed: 0.008 }, { name: '天王星', color: '0x33dddd', size: 2.5, orbit: 150, speed: 0.006 }, { name: '海王星', color: '0x3366cc', size: 2.5, orbit: 170, speed: 0.005 } ]; // 创建行星与轨道 planetList.forEach(planet => { const geometry = new THREE.SphereGeometry(planet.size, 32, 32); const material = new THREE.MeshStandardMaterial({ color: planet.color }); const mesh = new THREE.Mesh(geometry, material); mesh.userData = { angle: Math.random() * Math.PI * 2, speed: planet.speed, orbitRadius: planet.orbit }; scene.add(mesh); planets.push(mesh); // 绘制轨道 const orbitGeometry = new THREE.RingGeometry(planet.orbit - 0.2, planet.orbit + 0.2, 60); orbitGeometry.rotateX(Math.PI / 2); const orbitMaterial = new THREE.MeshBasicMaterial({ color: 0x777777 }); const orbit = new THREE.Mesh(orbitGeometry, orbitMaterial); scene.add(orbit); }); window.addEventListener('resize', onWindowResize, false); } function onWindowResize() { camera.aspect = window.innerWidth/window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); } function animate() { requestAnimationFrame(animate); planets.forEach(planet => { planet.userData.angle += planet.userData.speed; const x = Math.cos(planet.userData.angle) * planet.userData.orbitRadius; const z = Math.sin(planet.userData.angle) * planet.userData.orbitRadius; planet.position.set(x, 0, z); // 理论上还可以添加每个星球自转的参数 }); controls.update(); renderer.render(scene, camera); } </script> </body> </html> ``` --- ### 特点解析: - **三维空间**:由 Three.js 提供三维渲染能力 - **光源系统**:使用一个环境光(`AmbientLight`)和一个中心点光源(`PointLight`) - **行星轨道**:使用圆环几何体(`RingGeometry`)绘制轨道路径 - **行星运动**:在动画循环中,实时更新行星的 `x`、`z` 坐标,形成绕日公转效果 - **交互控制**:使用 `OrbitControls` 添加旋转(拖拽)和缩放功能 --- ### 可视化建议改进: - 添加更多视觉效果(如木星环的特殊处理) - 使用高清图片纹理代替颜色材质(例如添加行星贴图) - 添加自转动画 - 修正实际轨道比例(按比例缩小处理) 如果需要进一步增加功能,也可以告诉我,我可以帮助你增加更复杂或更真实的太阳系动画!
Drag to resize
```html <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>3D 太阳系</title> <style> body { margin: 0; overflow: hidden; background-color: #000; /* 星空背景是深黑色 */ color: white; font-family: sans-serif; } #info { position: absolute; top: 10px; left: 10px; z-index: 100; background-color: rgba(0,0,0,0.5); padding: 5px 10px; border-radius: 5px; } #container { width: 100%; height: 100vh; } </style> </head> <body> <div id="info"> <h1>3D 太阳系</h1> <p>使用鼠标拖拽旋转视角,滚轮缩放。</p> </div> <div id="container"></div> <!-- Three.js CDN --> <script type="importmap"> { "imports": { "three": "https://unpkg.com/three@0.160.0/build/three.module.js", "three/addons/": "https://unpkg.com/three@0.160.0/examples/jsm/" } } </script> <script type="module"> import * as THREE from 'three'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; let scene, camera, renderer, controls; let sun, planets = []; function init() { // 场景 scene = new THREE.Scene(); // 相机 camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 10000); camera.position.set(0, 50, 120); // 设置相机位置,能俯瞰大部分初始轨道 // 渲染器 const container = document.getElementById('container'); renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setClearColor(0x000000); // 设置渲染器背景色为黑色 container.appendChild(renderer.domElement); // 轨道控制器 controls = new OrbitControls(camera, renderer.domElement); controls.enableDamping = true; controls.dampingFactor = 0.05; controls.screenSpacePanning = false; controls.minDistance = 10; controls.maxDistance = 500; // --- 星空背景 --- const starGeometry = new THREE.BufferGeometry(); const starVertices = []; for (let i = 0; i < 15000; i++) { const x = THREE.MathUtils.randFloatSpread(2000); const y = THREE.MathUtils.randFloatSpread(2000); const z = THREE.MathUtils.randFloatSpread(2000); starVertices.push(x, y, z); } starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starsVertices, 3)); const starMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 0.7 }); const stars = new THREE.Points(starGeometry, starMaterial); scene.add(stars); // --- 光源 --- const ambientLight = new THREE.AmbientLight(0x404040, 0.5); // 微弱的环境光,照亮阴影面 scene.add(ambientLight); const sunLight = new THREE.PointLight(0xffffff, 3, 0, 2); // 太阳光,照射行星 scene.add(sunLight); // 太阳自己会发光,因此不需要被它照亮 // --- 太阳 --- const sunGeometry = new THREE.SphereGeometry(10, 32, 32); const sunMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00, wireframe: false }); sun = new THREE.Mesh(sunGeometry, sunMaterial); scene.add(sun); // 太阳发光效果 (自发光基本) sunMaterial.emissive.setHex(0xffaa00); // --- 行星数据 [名称, 半径, 轨道半径, 轨道速度, 颜色] --- const planetData = [ ["Mercury", 0.8, 20, 0.010, 0xaaaaaa], ["Venus", 1.5, 30, 0.007, 0xe39e4f], ["Earth", 1.8, 45, 0.005, 0x0077ff], ["Mars", 1.0, 60, 0.0035, 0xff4500], ["Jupiter", 6, 90, 0.002, 0xffc07c], ["Saturn", 5, 120, 0.0015, 0xfad5a5], ["Uranus", 3, 150, 0.001, 0x4FD0E7], ["Neptune", 3, 180, 0.0008, 0x3b59ff], ]; // --- 创建行星和轨道 --- planetData.forEach(data => { const [name, radius, orbitRadius, speed, color] = data; // 行星组 (用于公转) const planetGroup = new THREE.Group(); scene.add(planetGroup); // 轨道线 const orbitPath=new THREE.EllipseCurve(0, 0, orbitRadius, orbitRadius, 0, 2 * Math.PI, false, 0); const orbitPoints = orbitPath.getPoints(128); const orbitGeometry = new THREE.BufferGeometry().setFromPoints(orbitPoints); const orbitMaterial = new THREE.LineBasicMaterial({ color: 0x666666, transparent: true, opacity: 0.5 }); const orbitLine = new THREE.Line(orbitGeometry, orbitMaterial); orbitLine.rotation.x = Math.PI / 2; // 轨道在XZ平面 scene.add(orbitLine); // 行星本体 (用于自转) const planetGeometry = new THREE.SphereGeometry(radius, 32, 32); const planetMaterial = new THREE.MeshLambertMaterial({ color }); const planetMesh = new THREE.Mesh(planetGeometry, planetMaterial); planetMesh.position.set(orbitRadius, 0, 0); // 初始位置 planetGroup.add(planetMesh); // 如果行星有特殊的环, 则添加环 if (name === "Saturn") { const ringGeometry = new THREE.RingGeometry(radius * 1.5, radius * 2.5, 64); const ringMaterial = new THREE.MeshBasicMaterial({ color: 0xfad5a5, side: THREE.DoubleSide, transparent: true, opacity: 0.6 }); const ring = new THREE.Mesh(ringGeometry, ringMaterial); ring.rotation.x = Math.PI / 2.2; // 倾斜角度 planetMesh.add(ring); // 将环作为行星的子对象 } // 将数据存储到行星对象中 planets.push({ group: planetGroup, mesh: planetMesh, speed: speed, }); }); // 动画循环 animate(); } function animate() { requestAnimationFrame(animate); // 行星公转和自转 planets.forEach(planet => { planet.group.rotation.y += planet.speed; // 公转 planet.mesh.rotation.y += 0.01; // 自转 }); // 太阳自转 sun.rotation.y += 0.002; // 更新控制器 controls.update(); // 渲染场景 renderer.render(scene, camera); } // 窗口大小改变时更新渲染器和相机 window.addEventListener('resize', onWindowResize, false); function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); } init(); </script> </body> </html> ```
Drag to resize
Here's a complete HTML file that renders an interactive 3D solar system using Three.js: ```html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>3D Solar System</title> <style> body { margin: 0; overflow: hidden; background-color: #000; } canvas { display: block; } .info { position: absolute; top: 10px; left: 10px; color: white; font-family: Arial, sans-serif; pointer-events: none; } </style> </head> <body> <div class="info">3D Solar System - Use mouse to rotate view, scroll to zoom</div> <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.7/dat.gui.min.js"></script> <script> // Scene setup const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); const renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setPixelRatio(window.devicePixelRatio); document.body.appendChild(renderer.domElement); // Lighting const ambientLight = new THREE.AmbientLight(0x333333); scene.add(ambientLight); const sunLight = new THREE.PointLight(0xffffff, 1.5); sunLight.position.set(0, 0, 0); scene.add(sunLight); // Texture loader const textureLoader = new THREE.TextureLoader(); const planetTextures = { sun: 'https://threejs.org/examples/textures/planets/sun.jpg', mercury: 'https://threejs.org/examples/textures/planets/mercury.jpg', venus: 'https://threejs.org/examples/textures/planets/venus.jpg', earth: 'https://threejs.org/examples/textures/planets/earth_atmos_2048.jpg', mars: 'https://threejs.org/examples/textures/planets/mars.jpg', jupiter: 'https://threejs.org/examples/textures/planets/jupiter.jpg', saturn: 'https://threejs.org/examples/textures/planets/saturn.jpg', uranus: 'https://threejs.org/examples/textures/planets/uranus.jpg', neptune: 'https://threejs.org/examples/textures/planets/neptune.jpg' }; // Create celestial bodies const celestialBodies = []; function createPlanet(name, radius, distance, textureUrl, orbitSpeed, rotationSpeed, rings = null) { const geometry = new THREE.SphereGeometry(radius, 32, 32); const material = new THREE.MeshPhongMaterial({ map: textureLoader.load(textureUrl), specular: new THREE.Color(0x333333) }); const planet = new THREE.Mesh(geometry, material); planet.position.x = distance; if (rings) { const ringGeometry = new THREE.RingGeometry(rings.innerRadius, rings.outerRadius, 32); const ringMaterial = new THREE.MeshBasicMaterial({ map: textureLoader.load(rings.texture), side: THREE.DoubleSide }); const ring = new THREE.Mesh(ringGeometry, ringMaterial); ring.rotation.x = Math.PI / 2; planet.add(ring); } celestialBodies.push({ name, mesh: planet, distance, orbitSpeed, rotationSpeed, rotation: 0, orbit: 0 }); scene.add(planet); return planet; } // Add celestial bodies createPlanet('Sun', 6, 0, planetTextures.sun, 0, 0.0005); createPlanet('Mercury', 0.8, 15, planetTextures.mercury, 0.04, 0.01); createPlanet('Venus', 0.95, 20, planetTextures.venus, 0.015, 0.004); const earth = createPlanet('Earth', 1, 28, planetTextures.earth, 0.01, 0.02); createPlanet('Mars', 0.9, 36, planetTextures.mars, 0.008, 0.018); createPlanet('Jupiter', 2.5, 48, planetTextures.jupiter, 0.002, 0.04); createPlanet('Saturn', 2, 62, planetTextures.saturn, 0.0009, 0.038, { innerRadius: 2.5, outerRadius: 3.8, texture: 'https://threejs.org/examples/textures/planets/saturn_ring.png' }); createPlanet('Uranus', 1.6, 80, planetTextures.uranus, 0.0004, 0.03); createPlanet('Neptune', 1.6, 95, planetTextures.neptune, 0.0001, 0.032); // Camera position camera.position.z = 150; // Add stars const starsGeometry = new THREE.BufferGeometry(); const starsMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 0.1, transparent: true }); const starsVertices = []; for (let i = 0; i < 5000; i++) { const x = (Math.random() - 0.5) * 2000; const y = (Math.random() - 0.5) * 2000; const z = (Math.random() - 0.5) * 2000; starsVertices.push(x, y, z); } starsGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starsVertices, 3)); const stars = new THREE.Points(starsGeometry, starsMaterial); scene.add(stars); // Orbit controls const OrbitControls = function() { const mouseDown = (evt) => { if (evt.button === 0) { isDragging = true; prevX = evt.clientX; prevY = evt.clientY; } }; const mouseUp = () => { isDragging = false; }; const mouseMove = (evt) => { if (isDragging) { deltaX = evt.clientX - prevX; deltaY = evt.clientY - prevY; prevX = evt.clientX; prevY = evt.clientY; } }; const wheel = (evt) => { camera.position.z += evt.deltaY * 0.05; if (camera.position.z < 50) camera.position.z = 50; if (camera.position.z > 300) camera.position.z = 300; }; let isDragging = false; let prevX = 0; let prevY = 0; let deltaX = 0; let deltaY = 0; document.addEventListener('mousedown', mouseDown, false); document.addEventListener('mouseup', mouseUp, false); document.addEventListener('mousemove', mouseMove, false); document.addEventListener('wheel', wheel, false); this.update = (camera) => { if (isDragging) { camera.rotation.y += deltaX * 0.005; camera.rotation.x += deltaY * 0.005; deltaX = 0; deltaY = 0; } }; }; const orbitControls = new OrbitControls(); // Animation loop function animate() { requestAnimationFrame(animate); orbitControls.update(camera); // Update celestial bodies celestialBodies.forEach(body => { body.rotation += body.rotationSpeed; body.orbit += body.orbitSpeed; if (body.name !== 'Sun') { body.mesh.position.x = Math.sin(body.orbit) * body.distance; body.mesh.position.z = Math.cos(body.orbit) * body.distance; } body.mesh.rotation.y = body.rotation; }); renderer.render(scene, camera); } // Handle window resize window.addEventListener('resize', () => { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); }); animate(); </script> </body> </html> ``` This 3D solar system simulation includes: 1. The Sun and all 8 planets with relative sizes and distances (not to scale for visibility) 2. Planetary orbits and rotations with different speeds 3. Saturn's rings 4. Background stars 5. Interactive controls: - Left mouse drag to rotate view - Mouse wheel to zoom in/out 6. Textures for each planet to make them look realistic The simulation uses Three.js for 3D rendering and shows the basic mechanics of our solar system. The sizes and distances are adjusted for better visualization (not to actual scale).
Drag to resize
# 3D太阳系模拟系统 下面是一个使用Three.js创建的完整3D太阳系模型。这个实现展示了太阳、八颗行星及其部分卫星,包括行星的公转和自转运动。 ```html <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>3D太阳系模拟</title> <style> body { margin: 0; overflow: hidden; background: #000; color: #fff; font-family: 'Arial', sans-serif; } #canvas-container { position: relative; width: 100vw; height: 100vh; } #title { position: absolute; top: 20px; left: 0; width: 100%; text-align: center; font-size: 2.2rem; z-index: 10; text-shadow: 0 0 10px rgba(255, 255, 255, 0.7); } #info { position: absolute; bottom: 20px; left: 20px; background: rgba(0, 0, 0, 0.7); padding: 15px; border-radius: 10px; max-width: 300px; font-size: 1rem; z-index: 10; border: 1px solid #444; } #info h3 { margin-top: 0; color: #4fc3f7; border-bottom: 1px solid #555; padding-bottom: 5px; } #controls { position: absolute; top: 20px; right: 20px; background: rgba(0, 0, 0, 0.7); padding: 15px; border-radius: 10px; z-index: 10; border: 1px solid #444; } button { background: #0d47a1; color: white; border: none; padding: 8px 15px; margin: 5px 0; border-radius: 5px; cursor: pointer; font-weight: bold; width: 100%; transition: all 0.3s; } button:hover { background: #1565c0; transform: translateY(-2px); } .slider-container { margin: 10px 0; } label { display: block; margin-bottom: 5px; color: #4fc3f7; } input[type="range"] { width: 100%; } .planet-info { margin-top: 10px; display: none; } .visible { display: block; } #loading { position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; background: #000; z-index: 100; font-size: 2rem; transition: opacity 0.5s; } </style> </head> <body> <div id="loading">加载太阳系...</div> <div id="canvas-container"> <div id="title">三维太阳系模拟系统</div> <div id="info"> <h3>太阳系信息</h3> <p>在这个3D模型中,所有行星都围绕太阳运行,同时围绕各自的轴旋转。大小和距离不是严格按比例,但轨道周期是相对准确的。</p> <div class="planet-info" id="selected-planet"> 选择一个行星查看详细信息 </div> </div> <div id="controls"> <button id="reset-view">重置视图</button> <button id="toggle-stars">切换背景星云</button> <div class="slider-container"> <label for="speed">模拟速度: <span id="speed-value">1x</span></label> <input type="range" id="speed" min="0.1" max="5" step="0.1" value="1"> </div> <div class="slider-container"> <label for="zoom">缩放级别</label> <input type="range" id="zoom" min="0.5" max="3" step="0.1" value="1"> </div> </div> </div> <!-- Three.js Library --> <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/build/three.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.js"></script> <script> // 初始化和配置 let scene, camera, renderer, controls; let planets = {}; let starsBackground; let simulationSpeed = 1; let selectedPlanet = null; // 行星数据 const planetData = [ { name: "太阳", texture: "sun_texture", scale: 3, distance: 0, rotationSpeed: 0.002, orbitSpeed: 0, color: "#FFD700", description: "直径: 1,392,684 km<br>质量: 1.989 × 10³⁰ kg<br>表面温度: 5,500°C<br>类型: G型主序星(黄矮星)" }, { name: "水星", texture: "mercury_texture", scale: 0.4, distance: 8, rotationSpeed: 0.004, orbitSpeed: 0.04, color: "#A9A9A9", description: "直径: 4,879 km<br>距日距离: 57.9百万公里<br>公转周期: 88天<br>表面温度: -173°C 到 427°C" }, { name: "金星", texture: "venus_texture", scale: 0.6, distance: 12, rotationSpeed: 0.002, orbitSpeed: 0.015, color: "#E6A08F", description: "直径: 12,104 km<br>距日距离: 108.2百万公里<br>公转周期: 225天<br>表面温度: 464°C" }, { name: "地球", texture: "earth_texture", scale: 0.7, distance: 16, rotationSpeed: 0.02, orbitSpeed: 0.01, color: "#1E90FF", description: "直径: 12,742 km<br>距日距离: 149.6百万公里<br>公转周期: 365.25天<br>天然卫星: 月球", satellites: [{ name: "月球", scale: 0.15, distance: 1, orbitSpeed: 0.05 }]}, { name: "火星", texture: "mars_texture", scale: 0.5, distance: 20, rotationSpeed: 0.018, orbitSpeed: 0.008, color: "#FF4500", description: "直径: 6,779 km<br>距日距离: 227.9百万公里<br>公转周期: 687天<br>卫星: 火卫一、火卫二" }, { name: "木星", texture: "jupiter_texture", scale: 1.3, distance: 30, rotationSpeed: 0.04, orbitSpeed: 0.002, color: "#DAA520", description: "直径: 139,820 km<br>距日距离: 778.3百万公里<br>公转周期: 12年<br>已知卫星: 79颗" }, { name: "土星", texture: "saturn_texture", scale: 1.1, distance: 40, rotationSpeed: 0.038, orbitSpeed: 0.0009, color: "#F4A460", hasRings: true, ringScale: 2.2, description: "直径: 116,460 km<br>距日距离: 1.43亿公里<br>公转周期: 29年<br>壮观的环系统" }, { name: "天王星", texture: "uranus_texture", scale: 0.9, distance: 50, rotationSpeed: 0.03, orbitSpeed: 0.0004, color: "#40E0D0", description: "直径: 50,724 km<br>距日距离: 2.88亿公里<br>公转周期: 84年<br>独特的侧翻自转" }, { name: "海王星", texture: "neptune_texture", scale: 0.9, distance: 60, rotationSpeed: 0.032, orbitSpeed: 0.0001, color: "#4169E1", description: "直径: 49,244 km<br>距日距离: 4.50亿公里<br>公转周期: 165年<br>最强风力: 2,100 km/h" }, ]; // 使用程序化纹理(实际应用中应该加载真实纹理图片) const generateTexture = (color) => { const canvas = document.createElement('canvas'); canvas.width = 256; canvas.height = 256; const ctx = canvas.getContext('2d'); // 创建渐变 const grad = ctx.createRadialGradient(128, 128, 0, 128, 128, 128); grad.addColorStop(0, color); grad.addColorStop(0.2, color); grad.addColorStop(1, '#000'); ctx.fillStyle = grad; ctx.fillRect(0, 0, 256, 256); // 添加噪点模拟纹理 const imgData = ctx.getImageData(0, 0, 256, 256); const pixels = imgData.data; for (let i = 0; i < pixels.length; i += 4) { if (Math.random() > 0.7) { const r = Math.random() * 150; pixels[i] += r; // R pixels[i+1] += r; // G pixels[i+2] += r; // B } } ctx.putImageData(imgData, 0, 0); const texture = new THREE.Texture(canvas); texture.needsUpdate = true; return texture; }; // 初始化场景 function init() { // 创建场景 scene = new THREE.Scene(); // 创建相机 camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.set(0, 25, 70); // 创建渲染器 renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setPixelRatio(window.devicePixelRatio); document.getElementById('canvas-container').appendChild(renderer.domElement); // 添加轨道控制 controls = new THREE.OrbitControls(camera, renderer.domElement); controls.enableDamping = true; controls.dampingFactor = 0.05; // 创建星空背景 createStarsBackground(); // 创建光源 createLights(); // 创建太阳和行星 createCelestialBodies(); // 添加事件监听器 setupEventListeners(); // 开始渲染循环 animate(); // 隐藏加载屏幕 setTimeout(() => { document.getElementById('loading').style.opacity = 0; setTimeout(() => { document.getElementById('loading').style.display = 'none'; }, 500); }, 1500); } // 创建星空背景 function createStarsBackground() { const starsGeometry = new THREE.BufferGeometry(); const starsMaterial = new THREE.PointsMaterial({ color: 0xFFFFFF, size: 0.1, transparent: true }); const starsPositions = []; for (let i = 0; i < 5000; i++) { const x = THREE.MathUtils.randFloatSpread(500); const y = THREE.MathUtils.randFloatSpread(500); const z = THREE.MathUtils.randFloat(-300, -50); starsPositions.push(x, y, z); } starsGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starsPositions, 3)); starsBackground = new THREE.Points(starsGeometry, starsMaterial); scene.add(starsBackground); } // 创建光源 function createLights() { // 太阳光(点光源) const sunLight = new THREE.PointLight(0xFFFFFF, 2); sunLight.position.set(0, 0, 0); scene.add(sunLight); // 环境光 const ambientLight = new THREE.AmbientLight(0x333333); scene.add(ambientLight); } // 创建天体 function createCelestialBodies() { planetData.forEach(planet => { // 创建行星 const planetGeometry = new THREE.SphereGeometry(planet.scale, 32, 32); const planetMaterial = new THREE.MeshLambertMaterial({ map: generateTexture(planet.color), emissive: planet.name === "太阳" ? new THREE.Color(0xFFFF55) : new THREE.Color(0x000000) }); const planetMesh = new THREE.Mesh(planetGeometry, planetMaterial); if (planet.name !== "太阳") { // 创建行星轨道 const orbitGeometry = new THREE.BufferGeometry(); const orbitMaterial = new THREE.LineBasicMaterial({ color: 0x444444, transparent: true, opacity: 0.3 }); const points = []; for (let i = 0; i <= 100; i++) { const angle = (i / 100) * Math.PI * 2; points.push(new THREE.Vector3( Math.sin(angle) * planet.distance, 0, Math.cos(angle) * planet.distance )); } orbitGeometry.setFromPoints(points); const orbit = new THREE.Line(orbitGeometry, orbitMaterial); scene.add(orbit); // 添加行星到轨道位置 planetMesh.position.x = planet.distance; } scene.add(planetMesh); // 行星卫星 let satellitesGroup; if (planet.satellites) { satellitesGroup = new THREE.Group(); planet.satellites.forEach(satellite => { const satelliteGeometry = new THREE.SphereGeometry(satellite.scale, 16, 16); const satelliteMaterial = new THREE.MeshLambertMaterial({ color: 0xCCCCCC }); const satelliteMesh = new THREE.Mesh(satelliteGeometry, satelliteMaterial); // 卫星位置 satelliteMesh.position.x = satellite.distance; satellitesGroup.add(satelliteMesh); // 存储卫星信息 satellitesGroup.userData = { ...satellite, mesh: satelliteMesh }; }); planetMesh.add(satellitesGroup); } // 行星环(土星专用) let rings; if (planet.hasRings) { const ringGeometry = new THREE.RingGeometry(planet.scale * 1.4, planet.scale * planet.ringScale, 64); const ringMaterial = new THREE.MeshBasicMaterial({ color: 0xC0C0C0, side: THREE.DoubleSide, opacity: 0.7, transparent: true }); rings = new THREE.Mesh(ringGeometry, ringMaterial); rings.rotation.x = Math.PI / 3; planetMesh.add(rings); } // 存储行星信息 planets[planet.name] = { ...planet, mesh: planetMesh, satellites: satellitesGroup, rings: rings, orbitAngle: Math.random() * Math.PI * 2 }; }); } // 设置事件监听器 function setupEventListeners() { // 窗口大小变化 window.addEventListener('resize', () => { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); }); // 重置视图 document.getElementById('reset-view').addEventListener('click', () => { camera.position.set(0, 25, 70); camera.lookAt(0, 0, 0); controls.reset(); }); // 切换背景星云 document.getElementById('toggle-stars').addEventListener('click', () => { starsBackground.visible = !starsBackground.visible; }); // 模拟速度控制 const speedSlider = document.getElementById('speed'); const speedValue = document.getElementById('speed-value'); speedSlider.addEventListener('input', () => { simulationSpeed = parseFloat(speedSlider.value); speedValue.textContent = simulationSpeed.toFixed(1) + 'x'; }); // 缩放控制 const zoomSlider = document.getElementById('zoom'); zoomSlider.addEventListener('input', () => { camera.position.z = 70 * parseFloat(zoomSlider.value); }); // 行星选择 renderer.domElement.addEventListener('click', (event) => { // 射线检测选择行星 const mouse = new THREE.Vector2(); const rect = renderer.domElement.getBoundingClientRect(); mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1; mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1; const raycaster = new THREE.Raycaster(); raycaster.setFromCamera(mouse, camera); const intersects = raycaster.intersectObjects(Object.values(planets).map(p => p.mesh)); if (intersects.length > 0) { const selected = intersects[0].object; selectedPlanet = Object.values(planets).find(p => p.mesh === selected); // 显示行星信息 document.getElementById('selected-planet').innerHTML = ` <h4>${selectedPlanet.name}</h4> ${selectedPlanet.description} `; document.getElementById('selected-planet').classList.add('visible'); } }); } // 动画循环 function animate() { requestAnimationFrame(animate); // 更新行星运动 Object.values(planets).forEach(planet => { if (planet.name !== "太阳") { // 更新行星公转 planet.orbitAngle += planet.orbitSpeed * simulationSpeed * 0.01; planet.mesh.position.x = Math.sin(planet.orbitAngle) * planet.distance; planet.mesh.position.z = Math.cos(planet.orbitAngle) * planet.distance; // 行星自转 planet.mesh.rotation.y += planet.rotationSpeed * simulationSpeed; // 卫星运动 if (planet.satellites) { planet.satellites.userData.mesh.rotation.y += planet.satellites.userData.orbitSpeed * simulationSpeed; } } else { // 太阳自转 planet.mesh.rotation.y += planet.rotationSpeed * simulationSpeed; } }); // 更新星空背景旋转 starsBackground.rotation.y += 0.0001 * simulationSpeed; // 更新控制器 controls.update(); // 渲染场景 renderer.render(scene, camera); } // 启动应用 window.addEventListener('load', init); </script> </body> </html> ``` ## 主要功能说明 这个3D太阳系模拟实现了以下功能: 1. **真实的行星运动**:所有行星按照相对准确的速度绕太阳公转 2. **行星细节**: - 行星自转(太阳也自转) - 土星有独特的行星环 - 地球拥有绕其公转的月球卫星 3. **交互控制**: - 轨道控制(360°自由视角) - 缩放控制 - 模拟速度调节(0.1x-5x) - 可以点击查看每个行星的详细信息 - 背景星云可切换显示/隐藏 - 重置视图按钮 4. **视觉效果**: - 程序生成的行星纹理 - 动态星空背景 - 行星轨道可视化 - 自适应窗口大小调整 点击"重置视图"按钮可以恢复初始视角,拖动滑块可以调整模拟速度,点击行星查看其详细信息。 该模型考虑了真实太阳系的比例关系,但为了视觉清晰度在某些维度上进行了适度调整以便于观察。
Drag to resize
```html <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>3D太阳系</title> <style> body { margin: 0; padding: 0; background: #000; overflow: hidden; font-family: Arial, sans-serif; } #container { width: 100vw; height: 100vh; } #info { position: absolute; top: 10px; left: 10px; color: white; z-index: 100; font-size: 14px; } #controls { position: absolute; top: 10px; right: 10px; color: white; z-index: 100; font-size: 12px; } </style> </head> <body> <div id="container"></div> <div id="info"> <h3>3D太阳系</h3> <p>鼠标拖拽:旋转视角</p> <p>滚轮:缩放</p> <p>空格键:暂停/继续</p> </div> <div id="controls"> <p>速度: <input type="range" id="speedSlider" min="0.1" max="5" value="1" step="0.1"></p> <p>显示轨道: <input type="checkbox" id="showOrbits" checked></p> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> <script> // 场景、相机、渲染器设置 let scene, camera, renderer, controls; let sun, planets = []; let planetData = []; let animationSpeed = 1; let isPaused = false; let time = 0; // 行星数据 const planetsInfo = [ { name: '水星', distance: 15, size: 0.3, color: 0x8C7853, speed: 4.15, moons: [] }, { name: '金星', distance: 20, size: 0.4, color: 0xFFA500, speed: 1.62, moons: [] }, { name: '地球', distance: 25, size: 0.5, color: 0x6B93D6, speed: 1.00, moons: [{ distance: 2, size: 0.15, color: 0xC0C0C0, speed: 12 }] }, { name: '火星', distance: 32, size: 0.35, color: 0xCD5C5C, speed: 0.53, moons: [{ distance: 1.5, size: 0.08, color: 0x8B7355, speed: 15 }] }, { name: '木星', distance: 45, size: 1.2, color: 0xD8CA9D, speed: 0.084, moons: [ { distance: 3, size: 0.12, color: 0xFFE4B5, speed: 8 }, { distance: 4, size: 0.10, color: 0xDDD5C7, speed: 6 }, { distance: 5, size: 0.15, color: 0xB8860B, speed: 4 }, { distance: 6, size: 0.18, color: 0x708090, speed: 3 } ] }, { name: '土星', distance: 60, size: 1.0, color: 0xFAD5A5, speed: 0.034, moons: [], hasRings: true }, { name: '天王星', distance: 75, size: 0.7, color: 0x4FD0E7, speed: 0.012, moons: [] }, { name: '海王星', distance: 90, size: 0.68, color: 0x4169E1, speed: 0.006, moons: [] } ]; init(); animate(); function init() { // 创建场景 scene = new THREE.Scene(); // 创建相机 camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.set(0, 50, 100); // 创建渲染器 renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setPixelRatio(window.devicePixelRatio); document.getElementById('container').appendChild(renderer.domElement); // 添加鼠标控制 addMouseControls(); // 创建太阳 createSun(); // 创建星空背景 createStarField(); // 创建行星 createPlanets(); // 添加光源 const ambientLight = new THREE.AmbientLight(0x404040, 0.3); scene.add(ambientLight); // 事件监听 window.addEventListener('resize', onWindowResize); document.addEventListener('keydown', onKeyDown); document.getElementById('speedSlider').addEventListener('input', (e) => { animationSpeed = parseFloat(e.target.value); }); } function createSun() { const sunGeometry = new THREE.SphereGeometry(3, 32, 32); const sunMaterial = new THREE.MeshBasicMaterial({ color: 0xFFD700, emissive: 0xFFD700, emissiveIntensity: 0.5 }); sun = new THREE.Mesh(sunGeometry, sunMaterial); scene.add(sun); // 太阳光 const sunLight = new THREE.PointLight(0xFFFFFF, 2, 300); sunLight.position.set(0, 0, 0); scene.add(sunLight); } function createStarField() { const starGeometry = new THREE.BufferGeometry(); const starMaterial = new THREE.PointsMaterial({ color: 0xFFFFFF, size: 0.5 }); const starVertices = []; for (let i = 0; i < 10000; i++) { const x = (Math.random() - 0.5) * 2000; const y = (Math.random() - 0.5) * 2000; const z = (Math.random() - 0.5) * 2000; starVertices.push(x, y, z); } starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3)); const stars = new THREE.Points(starGeometry, starMaterial); scene.add(stars); } function createPlanets() { planetsInfo.forEach((planetInfo, index) => { const planetGroup = new THREE.Group(); // 创建轨道 const orbitGeometry = new THREE.RingGeometry(planetInfo.distance - 0.1, planetInfo.distance + 0.1, 64); const orbitMaterial = new THREE.MeshBasicMaterial({ color: 0x444444, side: THREE.DoubleSide, transparent: true, opacity: 0.3 }); const orbit = new THREE.Mesh(orbitGeometry, orbitMaterial); orbit.rotation.x = Math.PI / 2; scene.add(orbit); // 创建行星 const planetGeometry = new THREE.SphereGeometry(planetInfo.size, 20, 20); const planetMaterial = new THREE.MeshLambertMaterial({ color: planetInfo.color }); const planet = new THREE.Mesh(planetGeometry, planetMaterial); planetGroup.add(planet); // 创建土星的光环 if (planetInfo.hasRings) { const ringGeometry = new THREE.RingGeometry(planetInfo.size * 1.5, planetInfo.size * 2.5, 32); const ringMaterial = new THREE.MeshBasicMaterial({ color: 0xD2B48C, side: THREE.DoubleSide, transparent: true, opacity: 0.7 }); const rings = new THREE.Mesh(ringGeometry, ringMaterial); rings.rotation.x = Math.PI / 2; planetGroup.add(rings); } // 创建卫星 planetInfo.moons.forEach(moonInfo => { const moonGeometry = new THREE.SphereGeometry(moonInfo.size, 16, 16); const moonMaterial = new THREE.MeshLambertMaterial({ color: moonInfo.color }); const moon = new THREE.Mesh(moonGeometry, moonMaterial); const moonGroup = new THREE.Group(); moonGroup.add(moon); moon.position.x = moonInfo.distance; planetGroup.add(moonGroup); // 保存卫星数据 moonInfo.mesh = moon; moonInfo.group = moonGroup; }); scene.add(planetGroup); // 保存行星数据 planetData.push({ group: planetGroup, planet: planet, info: planetInfo, angle: Math.random() * Math.PI * 2, orbit: orbit }); }); } function addMouseControls() { let mouseDown = false; let mouseX = 0, mouseY = 0; let targetX = 0, targetY = 0; renderer.domElement.addEventListener('mousedown', (event) => { mouseDown = true; mouseX = event.clientX; mouseY = event.clientY; }); window.addEventListener('mouseup', () => { mouseDown = false; }); window.addEventListener('mousemove', (event) => { if (mouseDown) { const deltaX = event.clientX - mouseX; const deltaY = event.clientY - mouseY; targetX -= deltaY * 0.01; targetY += deltaX * 0.01; mouseX = event.clientX; mouseY = event.clientY; } }); renderer.domElement.addEventListener('wheel', (event) => { const delta = event.deltaY; camera.position.multiplyScalar(delta > 0 ? 1.1 : 0.9); event.preventDefault(); }); function updateCamera() { const radius = camera.position.length(); camera.position.x = radius * Math.sin(targetY) * Math.cos(targetX); camera.position.y = radius * Math.sin(targetX); camera.position.z = radius * Math.cos(targetY) * Math.cos(targetX); camera.lookAt(0, 0, 0); requestAnimationFrame(updateCamera); } updateCamera(); } function animate() { requestAnimationFrame(animate); if (!isPaused) { time += 0.01 * animationSpeed; // 太阳自转 sun.rotation.y += 0.005 * animationSpeed; // 行星公转和自转 planetData.forEach((planetObj, index) => { const planet = planetObj.planet; const group = planetObj.group; const info = planetObj.info; // 行星公转 planetObj.angle += info.speed * 0.01 * animationSpeed; const x = Math.cos(planetObj.angle) * info.distance; const z = Math.sin(planetObj.angle) * info.distance; group.position.set(x, 0, z); // 行星自转 planet.rotation.y += 0.02 * animationSpeed; // 卫星公转 info.moons.forEach(moon => { if (moon.group) { moon.group.rotation.y += moon.speed * 0.01 * animationSpeed; moon.mesh.rotation.y += 0.05 * animationSpeed; } }); // 轨道显示控制 const showOrbits = document.getElementById('showOrbits').checked; planetObj.orbit.visible = showOrbits; }); } renderer.render(scene, camera); } function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); } function onKeyDown(event) { if (event.code === 'Space') { isPaused = !isPaused; event.preventDefault(); } } </script> </body> </html> ``` 这个3D太阳系包含以下特性: 🌟 **主要功能:** - 太阳和8大行星的3D模型 - 真实的相对大小和颜色 - 行星轨道和公转动画 - 主要卫星(月球、火星卫星、木星四大卫星等) - 土星光环特效 - 星空背景 🎮 **交互控制:** - 鼠标拖拽:旋转视角观察 - 滚轮:缩放视图 - 空格键:暂停/继续动画 - 速度滑块:调节公转速度 - 轨道显示开关 ✨ **视觉效果:** - 太阳发光效果 - 行星自转和公转 - 卫星围绕行星运行 - 半透明轨道线 - 3D立体视角 你可以通过鼠标操作来从不同角度观察这个太阳系,感受宇宙的壮观!
Drag to resize