Spaces:
Build error
Build error
Download index.html from CarbonO2/anycoder-8767157c: direct link, hf CLI and curl.
- Browser
- Download file 31.1 kB
-
https://huggingface.co/spaces/CarbonO2/anycoder-8767157c/resolve/main/index.html
- Command line
-
hf download hf://spaces/CarbonO2/anycoder-8767157c/index.html
-
curl -L -o index.html https://huggingface.co/spaces/CarbonO2/anycoder-8767157c/resolve/main/index.html
31.1 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Interactive 3D Solar System</title> | |
| <style> | |
| @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&family=Exo+2:wght@300;400;600&display=swap'); | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| } | |
| :root { | |
| --primary: #00d4ff; | |
| --secondary: #ff6b35; | |
| --accent: #a855f7; | |
| --dark: #0a0a1a; | |
| --light: #e0e0ff; | |
| } | |
| body { | |
| font-family: 'Exo 2', sans-serif; | |
| background: var(--dark); | |
| color: var(--light); | |
| overflow: hidden; | |
| height: 100vh; | |
| } | |
| #canvas-container { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| z-index: 1; | |
| } | |
| .header { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| z-index: 100; | |
| padding: 1rem 2rem; | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| background: linear-gradient(180deg, rgba(10,10,26,0.9) 0%, transparent 100%); | |
| } | |
| .logo { | |
| font-family: 'Orbitron', sans-serif; | |
| font-size: 1.5rem; | |
| font-weight: 900; | |
| background: linear-gradient(135deg, var(--primary), var(--accent)); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| background-clip: text; | |
| text-transform: uppercase; | |
| letter-spacing: 3px; | |
| } | |
| .logo span { | |
| font-size: 0.8rem; | |
| color: var(--light); | |
| -webkit-text-fill-color: var(--light); | |
| opacity: 0.7; | |
| } | |
| .header a { | |
| color: var(--primary); | |
| text-decoration: none; | |
| font-size: 0.9rem; | |
| padding: 0.5rem 1rem; | |
| border: 1px solid var(--primary); | |
| border-radius: 20px; | |
| transition: all 0.3s ease; | |
| } | |
| .header a:hover { | |
| background: var(--primary); | |
| color: var(--dark); | |
| } | |
| .controls { | |
| position: fixed; | |
| bottom: 2rem; | |
| left: 2rem; | |
| z-index: 100; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 1rem; | |
| } | |
| .control-btn { | |
| background: rgba(0, 212, 255, 0.1); | |
| border: 1px solid var(--primary); | |
| color: var(--primary); | |
| padding: 0.8rem 1.2rem; | |
| border-radius: 8px; | |
| cursor: pointer; | |
| font-family: 'Orbitron', sans-serif; | |
| font-size: 0.8rem; | |
| transition: all 0.3s ease; | |
| backdrop-filter: blur(10px); | |
| } | |
| .control-btn:hover { | |
| background: var(--primary); | |
| color: var(--dark); | |
| transform: translateX(5px); | |
| } | |
| .control-btn.active { | |
| background: var(--primary); | |
| color: var(--dark); | |
| } | |
| .planet-info { | |
| position: fixed; | |
| top: 50%; | |
| right: -400px; | |
| transform: translateY(-50%); | |
| width: 350px; | |
| background: rgba(10, 10, 26, 0.95); | |
| border: 1px solid var(--primary); | |
| border-radius: 20px; | |
| padding: 2rem; | |
| z-index: 100; | |
| transition: right 0.5s cubic-bezier(0.4, 0, 0.2, 1); | |
| backdrop-filter: blur(20px); | |
| box-shadow: 0 0 50px rgba(0, 212, 255, 0.2); | |
| } | |
| .planet-info.visible { | |
| right: 2rem; | |
| } | |
| .planet-info h2 { | |
| font-family: 'Orbitron', sans-serif; | |
| font-size: 2rem; | |
| margin-bottom: 0.5rem; | |
| background: linear-gradient(135deg, var(--primary), var(--accent)); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| background-clip: text; | |
| } | |
| .planet-info .subtitle { | |
| color: var(--secondary); | |
| font-size: 0.9rem; | |
| margin-bottom: 1.5rem; | |
| text-transform: uppercase; | |
| letter-spacing: 2px; | |
| } | |
| .planet-info .stats { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 1rem; | |
| margin-bottom: 1.5rem; | |
| } | |
| .stat { | |
| background: rgba(0, 212, 255, 0.05); | |
| padding: 1rem; | |
| border-radius: 10px; | |
| text-align: center; | |
| } | |
| .stat-label { | |
| font-size: 0.7rem; | |
| text-transform: uppercase; | |
| letter-spacing: 1px; | |
| opacity: 0.7; | |
| margin-bottom: 0.3rem; | |
| } | |
| .stat-value { | |
| font-family: 'Orbitron', sans-serif; | |
| font-size: 1rem; | |
| color: var(--primary); | |
| } | |
| .planet-info .description { | |
| font-size: 0.9rem; | |
| line-height: 1.6; | |
| opacity: 0.8; | |
| margin-bottom: 1.5rem; | |
| } | |
| .close-btn { | |
| position: absolute; | |
| top: 1rem; | |
| right: 1rem; | |
| background: none; | |
| border: none; | |
| color: var(--light); | |
| font-size: 1.5rem; | |
| cursor: pointer; | |
| opacity: 0.7; | |
| transition: opacity 0.3s; | |
| } | |
| .close-btn:hover { | |
| opacity: 1; | |
| } | |
| .legend { | |
| position: fixed; | |
| bottom: 2rem; | |
| right: 2rem; | |
| z-index: 100; | |
| background: rgba(10, 10, 26, 0.9); | |
| border: 1px solid rgba(0, 212, 255, 0.3); | |
| border-radius: 15px; | |
| padding: 1.5rem; | |
| backdrop-filter: blur(10px); | |
| } | |
| .legend h3 { | |
| font-family: 'Orbitron', sans-serif; | |
| font-size: 0.9rem; | |
| margin-bottom: 1rem; | |
| color: var(--primary); | |
| } | |
| .legend-item { | |
| display: flex; | |
| align-items: center; | |
| gap: 0.5rem; | |
| margin-bottom: 0.5rem; | |
| font-size: 0.8rem; | |
| } | |
| .legend-dot { | |
| width: 12px; | |
| height: 12px; | |
| border-radius: 50%; | |
| } | |
| .loading { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| background: var(--dark); | |
| display: flex; | |
| flex-direction: column; | |
| justify-content: center; | |
| align-items: center; | |
| z-index: 1000; | |
| transition: opacity 0.5s ease; | |
| } | |
| .loading.hidden { | |
| opacity: 0; | |
| pointer-events: none; | |
| } | |
| .loading-spinner { | |
| width: 80px; | |
| height: 80px; | |
| border: 3px solid rgba(0, 212, 255, 0.1); | |
| border-top-color: var(--primary); | |
| border-radius: 50%; | |
| animation: spin 1s linear infinite; | |
| } | |
| @keyframes spin { | |
| to { transform: rotate(360deg); } | |
| } | |
| .loading-text { | |
| margin-top: 1.5rem; | |
| font-family: 'Orbitron', sans-serif; | |
| color: var(--primary); | |
| letter-spacing: 3px; | |
| } | |
| .speed-control { | |
| position: fixed; | |
| top: 50%; | |
| left: 2rem; | |
| transform: translateY(-50%); | |
| z-index: 100; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 0.5rem; | |
| } | |
| .speed-label { | |
| font-family: 'Orbitron', sans-serif; | |
| font-size: 0.7rem; | |
| color: var(--primary); | |
| text-transform: uppercase; | |
| letter-spacing: 2px; | |
| } | |
| .speed-slider { | |
| -webkit-appearance: none; | |
| width: 150px; | |
| height: 6px; | |
| background: rgba(0, 212, 255, 0.2); | |
| border-radius: 3px; | |
| outline: none; | |
| } | |
| .speed-slider::-webkit-slider-thumb { | |
| -webkit-appearance: none; | |
| width: 18px; | |
| height: 18px; | |
| background: var(--primary); | |
| border-radius: 50%; | |
| cursor: pointer; | |
| box-shadow: 0 0 10px var(--primary); | |
| } | |
| @media (max-width: 768px) { | |
| .planet-info { | |
| width: 100%; | |
| right: -100%; | |
| top: auto; | |
| bottom: 0; | |
| transform: none; | |
| border-radius: 20px 20px 0 0; | |
| } | |
| .planet-info.visible { | |
| right: 0; | |
| } | |
| .legend { | |
| display: none; | |
| } | |
| .controls { | |
| bottom: 1rem; | |
| left: 1rem; | |
| } | |
| .speed-control { | |
| left: 1rem; | |
| top: auto; | |
| bottom: 8rem; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="loading" id="loading"> | |
| <div class="loading-spinner"></div> | |
| <div class="loading-text">INITIALIZING SOLAR SYSTEM</div> | |
| </div> | |
| <div id="canvas-container"></div> | |
| <header class="header"> | |
| <div class="logo">Solar System <span>3D Model</span></div> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank">Built with anycoder</a> | |
| </header> | |
| <div class="controls"> | |
| <button class="control-btn active" id="toggle-orbits">Toggle Orbits</button> | |
| <button class="control-btn" id="toggle-labels">Toggle Labels</button> | |
| <button class="control-btn" id="reset-view">Reset View</button> | |
| </div> | |
| <div class="speed-control"> | |
| <span class="speed-label">Simulation Speed</span> | |
| <input type="range" class="speed-slider" id="speed-slider" min="0" max="100" value="30"> | |
| </div> | |
| <div class="planet-info" id="planet-info"> | |
| <button class="close-btn" onclick="closePlanetInfo()">×</button> | |
| <h2 id="info-name">Earth</h2> | |
| <div class="subtitle" id="info-type">Terrestrial Planet</div> | |
| <div class="stats"> | |
| <div class="stat"> | |
| <div class="stat-label">Diameter</div> | |
| <div class="stat-value" id="info-diameter">12,742 km</div> | |
| </div> | |
| <div class="stat"> | |
| <div class="stat-label">Distance from Sun</div> | |
| <div class="stat-value" id="info-distance">149.6M km</div> | |
| </div> | |
| <div class="stat"> | |
| <div class="stat-label">Orbital Period</div> | |
| <div class="stat-value" id="info-period">365.25 days</div> | |
| </div> | |
| <div class="stat"> | |
| <div class="stat-label">Moons</div> | |
| <div class="stat-value" id="info-moons">1</div> | |
| </div> | |
| </div> | |
| <p class="description" id="info-description"> | |
| The third planet from the Sun and the only astronomical object known to harbor life. | |
| </p> | |
| </div> | |
| <div class="legend"> | |
| <h3>Planets</h3> | |
| <div class="legend-item"><div class="legend-dot" style="background: #ffd700;"></div> Sun</div> | |
| <div class="legend-item"><div class="legend-dot" style="background: #b5651d;"></div> Mercury</div> | |
| <div class="legend-item"><div class="legend-dot" style="background: #e6c47a;"></div> Venus</div> | |
| <div class="legend-item"><div class="legend-dot" style="background: #4a90d9;"></div> Earth</div> | |
| <div class="legend-item"><div class="legend-dot" style="background: #c1440e;"></div> Mars</div> | |
| <div class="legend-item"><div class="legend-dot" style="background: #d4a574;"></div> Jupiter</div> | |
| <div class="legend-item"><div class="legend-dot" style="background: #e8c47a;"></div> Saturn</div> | |
| <div class="legend-item"><div class="legend-dot" style="background: #4fd0e8;"></div> Uranus</div> | |
| <div class="legend-item"><div class="legend-dot" style="background: #4b70dd;"></div> Neptune</div> | |
| </div> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.js"></script> | |
| <script> | |
| // Planet data | |
| const planetData = { | |
| mercury: { | |
| name: 'Mercury', | |
| type: 'Terrestrial Planet', | |
| diameter: '4,879 km', | |
| distance: '57.9M km', | |
| period: '88 days', | |
| moons: '0', | |
| description: 'The smallest planet in our solar system and closest to the Sun. Mercury has a heavily cratered surface similar to Earth\'s Moon.', | |
| color: 0xb5651d, | |
| size: 0.4, | |
| orbitRadius: 10, | |
| orbitSpeed: 4.15 | |
| }, | |
| venus: { | |
| name: 'Venus', | |
| type: 'Terrestrial Planet', | |
| diameter: '12,104 km', | |
| distance: '108.2M km', | |
| period: '225 days', | |
| moons: '0', | |
| description: 'The second planet from the Sun and Earth\'s closest neighbor. Venus has a thick, toxic atmosphere filled with carbon dioxide.', | |
| color: 0xe6c47a, | |
| size: 0.9, | |
| orbitRadius: 15, | |
| orbitSpeed: 1.62 | |
| }, | |
| earth: { | |
| name: 'Earth', | |
| type: 'Terrestrial Planet', | |
| diameter: '12,742 km', | |
| distance: '149.6M km', | |
| period: '365.25 days', | |
| moons: '1', | |
| description: 'The third planet from the Sun and the only astronomical object known to harbor life. About 71% of its surface is covered with water.', | |
| color: 0x4a90d9, | |
| size: 1, | |
| orbitRadius: 20, | |
| orbitSpeed: 1 | |
| }, | |
| mars: { | |
| name: 'Mars', | |
| type: 'Terrestrial Planet', | |
| diameter: '6,779 km', | |
| distance: '227.9M km', | |
| period: '687 days', | |
| moons: '2', | |
| description: 'The fourth planet from the Sun, often called the "Red Planet" due to iron oxide on its surface. Mars has the largest volcano in the solar system.', | |
| color: 0xc1440e, | |
| size: 0.5, | |
| orbitRadius: 25, | |
| orbitSpeed: 0.53 | |
| }, | |
| jupiter: { | |
| name: 'Jupiter', | |
| type: 'Gas Giant', | |
| diameter: '139,820 km', | |
| distance: '778.5M km', | |
| period: '11.86 years', | |
| moons: '79', | |
| description: 'The largest planet in our solar system. Jupiter is a gas giant with a mass more than twice that of all the other planets combined.', | |
| color: 0xd4a574, | |
| size: 3, | |
| orbitRadius: 35, | |
| orbitSpeed: 0.084 | |
| }, | |
| saturn: { | |
| name: 'Saturn', | |
| type: 'Gas Giant', | |
| diameter: '116,460 km', | |
| distance: '1.4B km', | |
| period: '29.46 years', | |
| moons: '82', | |
| description: 'The sixth planet from the Sun and famous for its beautiful ring system. Saturn is made mostly of hydrogen and helium.', | |
| color: 0xe8c47a, | |
| size: 2.5, | |
| orbitRadius: 45, | |
| orbitSpeed: 0.034 | |
| }, | |
| uranus: { | |
| name: 'Uranus', | |
| type: 'Ice Giant', | |
| diameter: '50,724 km', | |
| distance: '2.9B km', | |
| period: '84 years', | |
| moons: '27', | |
| description: 'The seventh planet from the Sun. Uranus has the coldest planetary atmosphere in the solar system and rotates on its side.', | |
| color: 0x4fd0e8, | |
| size: 1.8, | |
| orbitRadius: 55, | |
| orbitSpeed: 0.012 | |
| }, | |
| neptune: { | |
| name: 'Neptune', | |
| type: 'Ice Giant', | |
| diameter: '49,244 km', | |
| distance: '4.5B km', | |
| period: '164.8 years', | |
| moons: '14', | |
| description: 'The eighth and farthest known planet from the Sun. Neptune has the strongest winds in the solar system, reaching 2,100 km/h.', | |
| color: 0x4b70dd, | |
| size: 1.7, | |
| orbitRadius: 65, | |
| orbitSpeed: 0.006 | |
| } | |
| }; | |
| // Scene setup | |
| let scene, camera, renderer, controls; | |
| let planets = {}; | |
| let orbits = {}; | |
| let labels = {}; | |
| let showOrbits = true; | |
| let showLabels = false; | |
| let simulationSpeed = 0.3; | |
| let sun; | |
| function init() { | |
| // Scene | |
| scene = new THREE.Scene(); | |
| // Camera | |
| camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 2000); | |
| camera.position.set(0, 80, 120); | |
| // Renderer | |
| renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }); | |
| renderer.setSize(window.innerWidth, window.innerHeight); | |
| renderer.setPixelRatio(window.devicePixelRatio); | |
| renderer.toneMapping = THREE.ACESFilmicToneMapping; | |
| renderer.toneMappingExposure = 1; | |
| document.getElementById('canvas-container').appendChild(renderer.domElement); | |
| // Controls | |
| controls = new THREE.OrbitControls(camera, renderer.domElement); | |
| controls.enableDamping = true; | |
| controls.dampingFactor = 0.05; | |
| controls.minDistance = 20; | |
| controls.maxDistance = 500; | |
| // Create starfield | |
| createStarfield(); | |
| // Create Sun | |
| createSun(); | |
| // Create planets | |
| createPlanets(); | |
| // Lighting | |
| const ambientLight = new THREE.AmbientLight(0x333333); | |
| scene.add(ambientLight); | |
| const sunLight = new THREE.PointLight(0xffffff, 2, 500); | |
| sunLight.position.set(0, 0, 0); | |
| scene.add(sunLight); | |
| // Event listeners | |
| window.addEventListener('resize', onWindowResize); | |
| renderer.domElement.addEventListener('click', onMouseClick); | |
| // Control buttons | |
| document.getElementById('toggle-orbits').addEventListener('click', toggleOrbits); | |
| document.getElementById('toggle-labels').addEventListener('click', toggleLabels); | |
| document.getElementById('reset-view').addEventListener('click', resetView); | |
| document.getElementById('speed-slider').addEventListener('input', (e) => { | |
| simulationSpeed = e.target.value / 100; | |
| }); | |
| // Hide loading | |
| setTimeout(() => { | |
| document.getElementById('loading').classList.add('hidden'); | |
| }, 1500); | |
| // Start animation | |
| animate(); | |
| } | |
| function createStarfield() { | |
| const starsGeometry = new THREE.BufferGeometry(); | |
| const starCount = 10000; | |
| const positions = new Float32Array(starCount * 3); | |
| const colors = new Float32Array(starCount * 3); | |
| for (let i = 0; i < starCount * 3; i += 3) { | |
| const radius = 500 + Math.random() * 500; | |
| const theta = Math.random() * Math.PI * 2; | |
| const phi = Math.acos(2 * Math.random() - 1); | |
| positions[i] = radius * Math.sin(phi) * Math.cos(theta); | |
| positions[i + 1] = radius * Math.sin(phi) * Math.sin(theta); | |
| positions[i + 2] = radius * Math.cos(phi); | |
| const color = new THREE.Color(); | |
| color.setHSL(Math.random() * 0.2 + 0.5, 0.2, Math.random() * 0.5 + 0.5); | |
| colors[i] = color.r; | |
| colors[i + 1] = color.g; | |
| colors[i + 2] = color.b; | |
| } | |
| starsGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3)); | |
| starsGeometry.setAttribute('color', new THREE.BufferAttribute(colors, 3)); | |
| const starsMaterial = new THREE.PointsMaterial({ | |
| size: 1.5, | |
| vertexColors: true, | |
| transparent: true, | |
| opacity: 0.8 | |
| }); | |
| const stars = new THREE.Points(starsGeometry, starsMaterial); | |
| scene.add(stars); | |
| } | |
| function createSun() { | |
| // Sun sphere | |
| const sunGeometry = new THREE.SphereGeometry(5, 64, 64); | |
| const sunMaterial = new THREE.MeshBasicMaterial({ | |
| color: 0xffdd00, | |
| emissive: 0xffaa00, | |
| emissiveIntensity: 1 | |
| }); | |
| sun = new THREE.Mesh(sunGeometry, sunMaterial); | |
| scene.add(sun); | |
| // Sun glow | |
| const glowGeometry = new THREE.SphereGeometry(6, 32, 32); | |
| const glowMaterial = new THREE.MeshBasicMaterial({ | |
| color: 0xff8800, | |
| transparent: true, | |
| opacity: 0.3, | |
| side: THREE.BackSide | |
| }); | |
| const glow = new THREE.Mesh(glowGeometry, glowMaterial); | |
| scene.add(glow); | |
| // Outer glow | |
| const outerGlowGeometry = new THREE.SphereGeometry(8, 32, 32); | |
| const outerGlowMaterial = new THREE.MeshBasicMaterial({ | |
| color: 0xff4400, | |
| transparent: true, | |
| opacity: 0.1, | |
| side: THREE.BackSide | |
| }); | |
| const outerGlow = new THREE.Mesh(outerGlowGeometry, outerGlowMaterial); | |
| scene.add(outerGlow); | |
| // Create label | |
| createLabel('Sun', new THREE.Vector3(0, 8, 0), 0xffdd00); | |
| } | |
| function createPlanets() { | |
| const planetNames = Object.keys(planetData); | |
| planetNames.forEach((name, index) => { | |
| const data = planetData[name]; | |
| const angle = (index / planetNames.length) * Math.PI * 2; | |
| // Create orbit | |
| const orbitGeometry = new THREE.RingGeometry(data.orbitRadius - 0.1, data.orbitRadius + 0.1, 128); | |
| const orbitMaterial = new THREE.MeshBasicMaterial({ | |
| color: 0x00d4ff, | |
| transparent: true, | |
| opacity: 0.15, | |
| side: THREE.DoubleSide | |
| }); | |
| const orbit = new THREE.Mesh(orbitGeometry, orbitMaterial); | |
| orbit.rotation.x = Math.PI / 2; | |
| orbit.userData = { type: 'orbit' }; | |
| orbits[name] = orbit; | |
| scene.add(orbit); | |
| // Create planet group | |
| const planetGroup = new THREE.Group(); | |
| planetGroup.userData = { | |
| type: 'planet', | |
| name: name, | |
| orbitRadius: data.orbitRadius, | |
| orbitSpeed: data.orbitSpeed, | |
| angle: angle | |
| }; | |
| // Planet sphere | |
| const planetGeometry = new THREE.SphereGeometry(data.size, 32, 32); | |
| const planetMaterial = new THREE.MeshStandardMaterial({ | |
| color: data.color, | |
| roughness: 0.7, | |
| metalness: 0.3 | |
| }); | |
| const planet = new THREE.Mesh(planetGeometry, planetMaterial); | |
| planet.userData = { type: 'planet', name: name }; | |
| planetGroup.add(planet); | |
| // Position planet | |
| const x = Math.cos(angle) * data.orbitRadius; | |
| const z = Math.sin(angle) * data.orbitRadius; | |
| planetGroup.position.set(x, 0, z); | |
| planets[name] = planetGroup; | |
| scene.add(planetGroup); | |
| // Create label | |
| const labelY = data.size + 2; | |
| createLabel(data.name, new THREE.Vector3(x, labelY, z), data.color, name); | |
| }); | |
| // Add rings for Saturn | |
| const saturnRingGeometry = new THREE.RingGeometry(3.5, 5, 64); | |
| const saturnRingMaterial = new THREE.MeshBasicMaterial({ | |
| color: 0xc9a86c, | |
| transparent: true, | |
| opacity: 0.7, | |
| side: THREE.DoubleSide | |
| }); | |
| const saturnRing = new THREE.Mesh(saturnRingGeometry, saturnRingMaterial); | |
| saturnRing.rotation.x = Math.PI / 2.5; | |
| planets.saturn.add(saturnRing); | |
| } | |
| function createLabel(text, position, color, planetName = null) { | |
| const canvas = document.createElement('canvas'); | |
| const context = canvas.getContext('2d'); | |
| canvas.width = 256; | |
| canvas.height = 64; | |
| context.fillStyle = 'rgba(0, 0, 0, 0)'; | |
| context.fillRect(0, 0, canvas.width, canvas.height); | |
| context.font = 'bold 32px Orbitron'; | |
| context.textAlign = 'center'; | |
| context.fillStyle = '#' + color.toString(16).padStart(6, '0'); | |
| context.fillText(text, 128, 40); | |
| const texture = new THREE.CanvasTexture(canvas); | |
| const spriteMaterial = new THREE.SpriteMaterial({ | |
| map: texture, | |
| transparent: true, | |
| opacity: 0.8 | |
| }); | |
| const sprite = new THREE.Sprite(spriteMaterial); | |
| sprite.position.copy(position); | |
| sprite.scale.set(15, 4, 1); | |
| if (planetName) { | |
| labels[planetName] = sprite; | |
| sprite.visible = showLabels; | |
| } | |
| scene.add(sprite); | |
| } | |
| function toggleOrbits() { | |
| showOrbits = !showOrbits; | |
| document.getElementById('toggle-orbits').classList.toggle('active'); | |
| Object.values(orbits).forEach(orbit => { | |
| orbit.visible = showOrbits; | |
| }); | |
| } | |
| function toggleLabels() { | |
| showLabels = !showLabels; | |
| document.getElementById('toggle-labels').classList.toggle('active'); | |
| Object.values(labels).forEach(label => { | |
| label.visible = showLabels; | |
| }); | |
| } | |
| function resetView() { | |
| camera.position.set(0, 80, 120); | |
| controls.reset(); | |
| } | |
| function showPlanetInfo(name) { | |
| const data = planetData[name]; | |
| if (!data) return; | |
| document.getElementById('info-name').textContent = data.name; | |
| document.getElementById('info-type').textContent = data.type; | |
| document.getElementById('info-diameter').textContent = data.diameter; | |
| document.getElementById('info-distance').textContent = data.distance; | |
| document.getElementById('info-period').textContent = data.period; | |
| document.getElementById('info-moons').textContent = data.moons; | |
| document.getElementById('info-description').textContent = data.description; | |
| document.getElementById('planet-info').classList.add('visible'); | |
| } | |
| function closePlanetInfo() { | |
| document.getElementById('planet-info').classList.remove('visible'); | |
| } | |
| function onMouseClick(event) { | |
| const mouse = new THREE.Vector2(); | |
| mouse.x = (event.clientX / window.innerWidth) * 2 - 1; | |
| mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; | |
| const raycaster = new THREE.Raycaster(); | |
| raycaster.setFromCamera(mouse, camera); | |
| const planetObjects = []; | |
| Object.values(planets).forEach(group => { | |
| group.children.forEach(child => { | |
| if (child.userData.type === 'planet') { | |
| planetObjects.push(child); | |
| } | |
| }); | |
| }); | |
| const intersects = raycaster.intersectObjects(planetObjects); | |
| if (intersects.length > 0) { | |
| const planetName = intersects[0].object.userData.name; | |
| showPlanetInfo(planetName); | |
| } | |
| } | |
| function onWindowResize() { | |
| camera.aspect = window.innerWidth / window.innerHeight; | |
| camera.updateProjectionMatrix(); | |
| renderer.setSize(window.innerWidth, window.innerHeight); | |
| } | |
| function animate() { | |
| requestAnimationFrame(animate); | |
| // Rotate Sun | |
| sun.rotation.y += 0.002; | |
| // Animate planets | |
| Object.values(planets).forEach(planetGroup => { | |
| const data = planetGroup.userData; | |
| data.angle += data.orbitSpeed * simulationSpeed * 0.01; | |
| const x = Math.cos(data.angle) * data.orbitRadius; | |
| const z = Math.sin(data.angle) * data.orbitRadius; | |
| planetGroup.position.set(x, 0, z); | |
| // Rotate planet | |
| planetGroup.children[0].rotation.y += 0.02; | |
| // Update label position | |
| const planetName = data.name; | |
| if (labels[planetName]) { | |
| const planetData = planetData[planetName]; | |
| labels[planetName].position.set(x, planetData.size + 2, z); | |
| } | |
| }); | |
| controls.update(); | |
| renderer.render(scene, camera); | |
| } | |
| // Initialize | |
| init(); | |
| </script> | |
| </body> | |
| </html> |