讨论

交互式3D太阳系模拟器

来自 Wikiprompt,自由的提示词百科全书

Eyisha Zyer

2026年7月11日

交互式3D太阳系模拟器 使用Three.js构建精致3D太阳系模拟器的全面提示,包括逼真轨道、控制、UI和视觉增强。

提示词内容收藏

🌐
<!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; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: black; color: white; } #info { position: absolute; top: 20px; left: 20px; background: rgba(20, 20, 30, 0.7); backdrop-filter: blur(8px); border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 12px; padding: 12px 20px; color: #ddd; font-size: 14px; pointer-events: none; z-index: 100; box-shadow: 0 4px 20px rgba(0,0,0,0.5); letter-spacing: 0.5px; } #info span { color: #ffaa00; font-weight: bold; } #controls { position: absolute; bottom: 30px; left: 50%; transform: translateX(-50%); background: rgba(20, 20, 30, 0.7); backdrop-filter: blur(8px); border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 40px; padding: 12px 30px; display: flex; gap: 30px; align-items: center; z-index: 200; box-shadow: 0 4px 20px rgba(0,0,0,0.6); color: #eee; font-size: 16px; font-weight: 500; } #controls label { display: flex; align-items: center; gap: 10px; } #controls input[type="range"] { width: 180px; cursor: pointer; background: transparent; accent-color: #ffaa00; } #controls button { background: rgba(255, 170, 0, 0.2); border: 1px solid #ffaa00; color: #ffaa00; padding: 8px 20px; border-radius: 30px; font-weight: bold; cursor: pointer; transition: all 0.2s; letter-spacing: 0.5px; font-size: 14px; } #controls button:hover { background: #ffaa00; color: black; } #reset-btn { background: rgba(100, 200, 255, 0.2); border-color: #64c8ff; color: #64c8ff; } #reset-btn:hover { background: #64c8ff; color: black; } #status { position: absolute; bottom: 100px; right: 30px; background: rgba(20, 20, 30, 0.6); backdrop-filter: blur(4px); border: 1px solid rgba(255,255,255,0.1); border-radius: 8px; padding: 8px 16px; font-size: 14px; color: #aaa; z-index: 150; pointer-events: none; } #planet-label { position: absolute; top: 80px; left: 20px; background: rgba(0,0,0,0.5); padding: 6px 12px; border-radius: 20px; font-size: 14px; color: #ffaa00; border-left: 3px solid #ffaa00; pointer-events: none; opacity: 0; transition: opacity 0.3s; } .label-3d { color: #fff; text-shadow: 0 0 10px rgba(0,0,0,0.8); font-size: 12px; font-weight: bold; background: rgba(0,0,0,0.4); padding: 2px 8px; border-radius: 12px; border: 1px solid rgba(255,255,255,0.2); backdrop-filter: blur(2px); white-space: nowrap; pointer-events: none; } @media (max-width: 700px) { #controls { flex-wrap: wrap; width: 90%; padding: 15px; gap: 15px; justify-content: center; } #controls input[type="range"] { width: 120px; } } </style> </head> <body> <div id="info">🌌 <span>太阳系模拟器</span> · 拖动旋转 · 滚轮缩放 · 点击行星聚焦</div> <div id="planet-label"></div> <div id="status">速度: <span id="speed-display">1.0x</span> · 状态: <span id="pause-status">运行中</span></div> <div id="controls"> <label>⚡ 速度 <input type="range" id="speed-slider" min="0" max="5" step="0.1" value="1"></label> <button id="pause-btn">⏸️ 暂停</button> <button id="reset-btn">↺ 重置视角</button> </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; renderer.setPixelRatio(window.devicePixelRatio); document.body.appendChild(renderer.domElement); // CSS2D渲染器 (用于标签) 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.rotateSpeed = 0.8; controls.zoomSpeed = 1.2; controls.minDistance = 5; controls.maxDistance = 200; controls.target.set(0, 0, 0); // --- 光照 --- // 环境光提供基础照明 const ambientLight = new THREE.AmbientLight(0x404060); scene.add(ambientLight); // 点光源模拟太阳光 const sunLight = new THREE.PointLight(0xffdd99, 2, 0, 0); sunLight.position.set(0, 0, 0); scene.add(sunLight); // 辅助光让行星背面可见 const backLight = new THREE.DirectionalLight(0x446688, 0.3); backLight.position.set(-10, 10, -20); scene.add(backLight); // 添加一点暖色补光 const fillLight = new THREE.DirectionalLight(0xffaa88, 0.2); fillLight.position.set(10, 5, 10); scene.add(fillLight); // --- 星空背景 (粒子系统) --- const starsGeometry = new THREE.BufferGeometry(); const starsCount = 6000; const starsPositions = new Float32Array(starsCount * 3); for (let i = 0; i < starsCount * 3; i += 3) { // 随机分布在球壳上 const r = 150 + Math.random() * 100; const theta = Math.random() * Math.PI * 2; const phi = Math.acos((Math.random() * 2) - 1); starsPositions[i] = r * Math.sin(phi) * Math.cos(theta); starsPositions[i+1] = r * Math.sin(phi) * Math.sin(theta); starsPositions[i+2] = r * Math.cos(phi); } starsGeometry.setAttribute('position', new THREE.BufferAttribute(starsPositions, 3)); const starsMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 0.25, transparent: true, opacity: 0.8 }); const stars = new THREE.Points(starsGeometry, starsMaterial); scene.add(stars); // 额外的小星星闪烁效果 (用第二层粒子) const twinkleStarsGeo = new THREE.BufferGeometry(); const twinkleCount = 2000; const twinklePos = new Float32Array(twinkleCount * 3); for (let i = 0; i < twinkleCount * 3; i += 3) { const r = 200 + Math.random() * 150; const theta = Math.random() * Math.PI * 2; const phi = Math.acos((Math.random() * 2) - 1); twinklePos[i] = r * Math.sin(phi) * Math.cos(theta); twinklePos[i+1] = r * Math.sin(phi) * Math.sin(theta); twinklePos[i+2] = r * Math.cos(phi); } twinkleStarsGeo.setAttribute('position', new THREE.BufferAttribute(twinklePos, 3)); const twinkleMaterial = new THREE.PointsMaterial({ color: 0x88aaff, size: 0.15, transparent: true, opacity: 0.6 }); const twinkleStars = new THREE.Points(twinkleStarsGeo, twinkleMaterial); scene.add(twinkleStars); // --- 太阳 --- const sunGeometry = new THREE.SphereGeometry(3.5, 64, 64); const sunMaterial = new THREE.MeshStandardMaterial({ color: 0xffaa33, 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 * 3; i += 3) { const r = 4.0 + Math.random() * 1.5; const theta = Math.random() * Math.PI * 2; const phi = Math.acos((Math.random() * 2) - 1); glowPos[i] = r * Math.sin(phi) * Math.cos(theta); glowPos[i+1] = r * Math.sin(phi) * Math.sin(theta); glowPos[i+2] = r * Math.cos(phi); } glowParticlesGeo.setAttribute('position', new THREE.BufferAttribute(glowPos, 3)); const glowMaterial = new THREE.PointsMaterial({ color: 0xffaa44, size: 0.08, transparent: true, blending: THREE.AdditiveBlending }); const glow = new THREE.Points(glowParticlesGeo, glowMaterial); scene.add(glow); // --- 行星数据 --- // 为了视觉效果,大小和距离不按真实比例,但保持相对关系 const planetsData = [ { name: '水星', radius: 0.4, distance: 6.0, color: 0xaaaaaa, speed: 0.02, emissive: 0x222222 }, { name: '金星', radius: 0.6, distance: 9.0, color: 0xffcc88, speed: 0.015, emissive: 0x442200 }, { name: '地球', radius: 0.65, distance: 12.0, color: 0x4488ff, speed: 0.012, emissive: 0x002244 }, { name: '火星', radius: 0.55, distance: 15.0, color: 0xff6633, speed: 0.01, emissive: 0x331100 }, { name: '木星', radius: 1.4, distance: 19.0, color: 0xddbb99, speed: 0.008, emissive: 0x332211 }, { name: '土星', radius: 1.2, distance: 24.0, color: 0xeeddbb, speed: 0.006, emissive: 0x332211, hasRing: true }, { name: '天王星', radius: 0.9, distance: 29.0, color: 0x88ccff, speed: 0.005, emissive: 0x113344 }, { name: '海王星', radius: 0.9, distance: 34.0, color: 0x3366ff, speed: 0.004, emissive: 0x001133 } ]; // 存储行星对象以便动画 const planets = []; const orbitLines = []; // 创建行星和轨道 planetsData.forEach((data, index) => { // 创建行星球体 const geometry = new THREE.SphereGeometry(data.radius, 32, 32); const material = new THREE.MeshStandardMaterial({ color: data.color, emissive: data.emissive, emissiveIntensity: 0.1, roughness: 0.5, metalness: 0.1 }); const planet = new THREE.Mesh(geometry, material); // 初始位置 const angle = Math.random() * Math.PI * 2; planet.position.x = data.distance * Math.cos(angle); planet.position.z = data.distance * Math.sin(angle); // 存储自定义属性 planet.userData = { distance: data.distance, speed: data.speed, angle: angle, name: data.name }; scene.add(planet); planets.push(planet); // 如果是土星,添加光环 if (data.hasRing) { const ringGeo = new THREE.TorusGeometry(data.radius * 1.8, 0.2, 16, 100); const ringMat = new THREE.MeshStandardMaterial({ color: 0xccbb99, emissive: 0x332211, side: THREE.DoubleSide, transparent: true, opacity: 0.6 }); const ring = new THREE.Mesh(ringGeo, ringMat); ring.rotation.x = Math.PI / 2; ring.rotation.z = 0.3; planet.add(ring); } // 创建轨道线 (半透明圆环) const orbitPoints = []; const segments = 128; for (let i = 0; i <= segments; i++) { const theta = (i / segments) * Math.PI * 2; const x = data.distance * Math.cos(theta); const z = data.distance * Math.sin(theta); orbitPoints.push(new THREE.Vector3(x, 0, z)); } const orbitGeometry = new THREE.BufferGeometry().setFromPoints(orbitPoints); const orbitMaterial = new THREE.LineBasicMaterial({ color: 0x88aaff, opacity: 0.2, transparent: true }); const orbitLine = new THREE.Line(orbitGeometry, orbitMaterial); scene.add(orbitLine); orbitLines.push(orbitLine); // 创建CSS2D标签 const labelDiv = document.createElement('div'); labelDiv.className = 'label-3d'; labelDiv.textContent = data.name; const label = new CSS2DObject(labelDiv); label.position.set(0, data.radius + 0.8, 0); planet.add(label); }); // 添加小行星带 (装饰) const asteroidGeo = new THREE.BufferGeometry(); const astCount = 800; const astPos = new Float32Array(astCount * 3); for (let i = 0; i < astCount * 3; i += 3) { const r = 17 + Math.random() * 2.5; const theta = Math.random() * Math.PI * 2; const y = (Math.random() - 0.5) * 0.8; astPos[i] = r * Math.cos(theta); astPos[i+1] = y; astPos[i+2] = r * Math.sin(theta); } asteroidGeo.setAttribute('position', new THREE.BufferAttribute(astPos, 3)); const astMat = new THREE.PointsMaterial({ color: 0xaa9977, size: 0.08 }); const asteroids = new THREE.Points(asteroidGeo, astMat); scene.add(asteroids); // --- UI 元素绑定 --- const speedSlider = document.getElementById('speed-slider'); const speedDisplay = document.getElementById('speed-display'); const pauseBtn = document.getElementById('pause-btn'); const resetBtn = document.getElementById('reset-btn'); const pauseStatus = document.getElementById('pause-status'); const planetLabel = document.getElementById('planet-label'); let isPaused = false; let speedMultiplier = 1.0; speedSlider.addEventListener('input', (e) => { speedMultiplier = parseFloat(e.target.value); speedDisplay.textContent = speedMultiplier.toFixed(1) + 'x'; }); pauseBtn.addEventListener('click', () => { isPaused = !isPaused; pauseBtn.textContent = isPaused ? '▶️ 继续' : '⏸️ 暂停'; pauseStatus.textContent = isPaused ? '已暂停' : '运行中'; }); resetBtn.addEventListener('click', () => { camera.position.set(0, 30, 60); controls.target.set(0, 0, 0); controls.update(); }); // 点击行星聚焦 (Raycaster) const raycaster = new THREE.Raycaster(); const mouse = new THREE.Vector2(); renderer.domElement.addEventListener('click', (event) => { mouse.x = (event.clientX / window.innerWidth) * 2 - 1; mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; raycaster.setFromCamera(mouse, camera); const intersects = raycaster.intersectObjects(planets); if (intersects.length > 0) { const targetPlanet = intersects[0].object; // 平滑移动相机到行星附近 (简单实现) const planetPos = targetPlanet.position.clone(); const offset = new THREE.Vector3(2, 2, 2).normalize().multiplyScalar(targetPlanet.userData.distance * 0.3); camera.position.copy(planetPos.clone().add(offset)); controls.target.copy(planetPos); controls.update(); // 显示标签 planetLabel.textContent = '🔭 聚焦: ' + targetPlanet.userData.name; planetLabel.style.opacity = 1; setTimeout(() => { planetLabel.style.opacity = 0; }, 2000); } }); // 键盘空格暂停 window.addEventListener('keydown', (e) => { if (e.code === 'Space') { e.preventDefault(); pauseBtn.click(); } }); // 窗口大小自适应 window.addEventListener('resize', () => { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); labelRenderer.setSize(window.innerWidth, window.innerHeight); }); // --- 动画循环 --- let clock = new THREE.Clock(); function animate() { const delta = clock.getDelta(); const elapsedTime = performance.now() * 0.001; // seconds if (!isPaused) { // 更新行星位置 planets.forEach(planet => { const data = planet.userData; data.angle += data.speed * speedMultiplier * delta * 2; // 乘2让速度更明显 planet.position.x = data.distance * Math.cos(data.angle); planet.position.z = data.distance * Math.sin(data.angle); }); // 小行星带旋转 asteroids.rotation.y += 0.001 * speedMultiplier; } // 星星缓慢旋转 stars.rotation.y += 0.0001; twinkleStars.rotation.y -= 0.00005; // 太阳自转 sun.rotation.y += 0.002; glow.rotation.y += 0.001; // 更新控制器 controls.update(); // 渲染 renderer.render(scene, camera); labelRenderer.render(scene, camera); requestAnimationFrame(animate); } animate(); // 初始状态显示 speedDisplay.textContent = '1.0x'; pauseStatus.textContent = '运行中'; </script> </body> </html>

登录以查看完整提示词

继续使用:

登录即表示你同意我们的 使用条款 和 隐私政策

用法

此提示词专为 coding 设计。复制上方内容并粘贴到你常用的 AI 工具中。

为获得最佳效果,可将占位符(方括号或大写字母标示)替换为你的具体需求。

参考资料

分类:coding| twitter| three-js| 3d-simulation

讨论