Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>3D Solar System Model</title> | |
| <script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/controls/OrbitControls.js"></script> | |
| <style> | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| font-family: 'Arial', sans-serif; | |
| } | |
| body { | |
| background: linear-gradient(135deg, #000428, #004e92); | |
| color: white; | |
| overflow: hidden; | |
| height: 100vh; | |
| } | |
| #container { | |
| position: absolute; | |
| width: 100%; | |
| height: 100%; | |
| } | |
| #info { | |
| position: absolute; | |
| bottom: 20px; | |
| left: 20px; | |
| background: rgba(0, 0, 0, 0.7); | |
| padding: 15px; | |
| border-radius: 10px; | |
| max-width: 300px; | |
| } | |
| #info h2 { | |
| margin-bottom: 10px; | |
| color: #ff9d00; | |
| } | |
| #controls { | |
| position: absolute; | |
| top: 20px; | |
| right: 20px; | |
| background: rgba(0, 0, 0, 0.7); | |
| padding: 15px; | |
| border-radius: 10px; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 10px; | |
| } | |
| .control-group { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| } | |
| button { | |
| background: #ff9d00; | |
| color: #000; | |
| border: none; | |
| padding: 8px 12px; | |
| border-radius: 5px; | |
| cursor: pointer; | |
| font-weight: bold; | |
| transition: all 0.3s; | |
| } | |
| button:hover { | |
| background: #ffc107; | |
| transform: translateY(-2px); | |
| } | |
| .planet-info { | |
| display: none; | |
| position: absolute; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| background: rgba(0, 0, 0, 0.9); | |
| padding: 20px; | |
| border-radius: 10px; | |
| width: 300px; | |
| z-index: 100; | |
| border: 2px solid #ff9d00; | |
| } | |
| .planet-info h3 { | |
| color: #ff9d00; | |
| margin-bottom: 10px; | |
| text-align: center; | |
| } | |
| .planet-info p { | |
| margin-bottom: 8px; | |
| } | |
| .close-btn { | |
| position: absolute; | |
| top: 10px; | |
| right: 10px; | |
| background: #ff9d00; | |
| color: #000; | |
| border: none; | |
| width: 25px; | |
| height: 25px; | |
| border-radius: 50%; | |
| cursor: pointer; | |
| font-weight: bold; | |
| } | |
| #loading { | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| background: #000; | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| flex-direction: column; | |
| z-index: 1000; | |
| } | |
| .loader { | |
| border: 5px solid #f3f3f3; | |
| border-top: 5px solid #ff9d00; | |
| border-radius: 50%; | |
| width: 50px; | |
| height: 50px; | |
| animation: spin 1s linear infinite; | |
| margin-bottom: 20px; | |
| } | |
| @keyframes spin { | |
| 0% { transform: rotate(0deg); } | |
| 100% { transform: rotate(360deg); } | |
| } | |
| #title { | |
| position: absolute; | |
| top: 20px; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| background: rgba(0, 0, 0, 0.7); | |
| padding: 10px 20px; | |
| border-radius: 10px; | |
| font-size: 24px; | |
| color: #ff9d00; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="loading"> | |
| <div class="loader"></div> | |
| <p>Loading Solar System...</p> | |
| </div> | |
| <div id="container"></div> | |
| <div id="title">3D Solar System Explorer</div> | |
| <div id="info"> | |
| <h2>Solar System Facts</h2> | |
| <p>Click on any planet to learn more about it. Use your mouse to rotate the view and scroll to zoom in/out.</p> | |
| </div> | |
| <div id="controls"> | |
| <div class="control-group"> | |
| <button id="speedUp">Speed Up Orbits</button> | |
| <button id="speedDown">Slow Down Orbits</button> | |
| </div> | |
| <div class="control-group"> | |
| <button id="zoomIn">Zoom In</button> | |
| <button id="zoomOut">Zoom Out</button> | |
| </div> | |
| <button id="resetView">Reset View</button> | |
| </div> | |
| <div id="planetInfo" class="planet-info"> | |
| <button class="close-btn">X</button> | |
| <h3 id="planetName">Planet Name</h3> | |
| <p>Type: <span id="planetType"></span></p> | |
| <p>Diameter: <span id="planetDiameter"></span></p> | |
| <p>Distance from Sun: <span id="planetDistance"></span></p> | |
| <p>Orbital Period: <span id="planetPeriod"></span></p> | |
| <p>Moons: <span id="planetMoons"></span></p> | |
| <p>Fun Fact: <span id="planetFact"></span></p> | |
| </div> | |
| <script> | |
| // Wait for the DOM to load | |
| document.addEventListener('DOMContentLoaded', function() { | |
| // Hide loading screen after a short delay | |
| setTimeout(() => { | |
| document.getElementById('loading').style.display = 'none'; | |
| initSolarSystem(); | |
| }, 1500); | |
| // Close planet info | |
| document.querySelector('.close-btn').addEventListener('click', function() { | |
| document.getElementById('planetInfo').style.display = 'none'; | |
| }); | |
| }); | |
| function initSolarSystem() { | |
| // Scene setup | |
| const scene = new THREE.Scene(); | |
| const container = document.getElementById('container'); | |
| const width = container.clientWidth; | |
| const height = container.clientHeight; | |
| // Camera setup | |
| const camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000); | |
| camera.position.z = 30; | |
| // Renderer setup | |
| const renderer = new THREE.WebGLRenderer({ antialias: true }); | |
| renderer.setSize(width, height); | |
| renderer.setPixelRatio(window.devicePixelRatio); | |
| renderer.setClearColor(0x000000); | |
| container.appendChild(renderer.domElement); | |
| // Controls | |
| const controls = new THREE.OrbitControls(camera, renderer.domElement); | |
| controls.enableDamping = true; | |
| controls.dampingFactor = 0.05; | |
| controls.minDistance = 10; | |
| controls.maxDistance = 100; | |
| // Lighting | |
| const ambientLight = new THREE.AmbientLight(0x404040); | |
| scene.add(ambientLight); | |
| const sunLight = new THREE.PointLight(0xffd700, 1.5, 300); | |
| sunLight.position.set(0, 0, 0); | |
| scene.add(sunLight); | |
| // Planets data | |
| const planetsData = [ | |
| { | |
| name: 'Mercury', | |
| radius: 0.4, | |
| distance: 5, | |
| color: 0xA9A9A9, | |
| speed: 0.04, | |
| type: 'Terrestrial', | |
| diameter: '4,879 km', | |
| orbitalPeriod: '88 Earth days', | |
| moons: '0', | |
| fact: 'Mercury has no atmosphere to retain heat, so temperatures swing between 430°C day and -180°C night.' | |
| }, | |
| { | |
| name: 'Venus', | |
| radius: 0.6, | |
| distance: 7, | |
| color: 0xf5f5dc, | |
| speed: 0.015, | |
| type: 'Terrestrial', | |
| diameter: '12,104 km', | |
| orbitalPeriod: '225 Earth days', | |
| moons: '0', | |
| fact: 'Venus rotates in the opposite direction to most planets and has days longer than its years!' | |
| }, | |
| { | |
| name: 'Earth', | |
| radius: 0.6, | |
| distance: 10, | |
| color: 0x1E88E5, | |
| speed: 0.01, | |
| type: 'Terrestrial', | |
| diameter: '12,742 km', | |
| orbitalPeriod: '365 Earth days', | |
| moons: '1 (Moon)', | |
| fact: 'Earth is the only known planet with liquid water on its surface and life as we know it.' | |
| }, | |
| { | |
| name: 'Mars', | |
| radius: 0.5, | |
| distance: 15, | |
| color: 0xff4500, | |
| speed: 0.008, | |
| type: 'Terrestrial', | |
| diameter: '6,779 km', | |
| orbitalPeriod: '687 Earth days', | |
| moons: '2 (Phobos & Deimos)', | |
| fact: 'Mars has the largest volcano in the solar system (Olympus Mons) and might have had oceans in the past.' | |
| }, | |
| { | |
| name: 'Jupiter', | |
| radius: 1.4, | |
| distance: 20, | |
| color: 0xff8c00, | |
| speed: 0.002, | |
| type: 'Gas Giant', | |
| diameter: '139,820 km', | |
| orbitalPeriod: '4,333 Earth days', | |
| moons: '79+', | |
| fact: "Jupiter's Great Red Spot is a storm that has raged for at least 350 years and could fit 3 Earths inside it." | |
| }, | |
| { | |
| name: 'Saturn', | |
| radius: 1.2, | |
| distance: 25, | |
| color: 0xffd700, | |
| speed: 0.0009, | |
| type: 'Gas Giant', | |
| diameter: '116,460 km', | |
| orbitalPeriod: '10,756 Earth days', | |
| moons: '82+', | |
| fact: "Saturn's rings are made of billions of ice particles ranging from dust-sized to mountain-sized." | |
| }, | |
| { | |
| name: 'Uranus', | |
| radius: 0.9, | |
| distance: 30, | |
| color: 0x87CEFA, | |
| speed: 0.0004, | |
| type: 'Ice Giant', | |
| diameter: '50,724 km', | |
| orbitalPeriod: '30,687 Earth days', | |
| moons: '27+', | |
| fact: 'Uranus rotates on its side (almost 90° tilt), likely due to a massive collision early in its history.' | |
| }, | |
| { | |
| name: 'Neptune', | |
| radius: 0.9, | |
| distance: 35, | |
| color: 0x4169E1, | |
| speed: 0.0001, | |
| type: 'Ice Giant', | |
| diameter: '49,244 km', | |
| orbitalPeriod: '60,190 Earth days', | |
| moons: '14+', | |
| fact: 'Neptune has the strongest winds in the solar system (over 2,100 km/h) despite being the coldest planet.' | |
| } | |
| ]; | |
| // Stars | |
| function addStars() { | |
| const starsGeometry = new THREE.BufferGeometry(); | |
| const starsMaterial = new THREE.PointsMaterial({ | |
| color: 0xFFFFFF, | |
| size: 0.1, | |
| transparent: true | |
| }); | |
| const starsVertices = []; | |
| 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; | |
| starsVertices.push(x, y, z); | |
| } | |
| starsGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starsVertices, 3)); | |
| const stars = new THREE.Points(starsGeometry, starsMaterial); | |
| scene.add(stars); | |
| } | |
| addStars(); | |
| // Sun | |
| const sunGeometry = new THREE.SphereGeometry(1.8, 32, 32); | |
| const sunMaterial = new THREE.MeshBasicMaterial({ | |
| color: 0xffd700, | |
| emissive: 0xffd700, | |
| emissiveIntensity: 1 | |
| }); | |
| const sun = new THREE.Mesh(sunGeometry, sunMaterial); | |
| scene.add(sun); | |
| // Sun glow effect | |
| const sunGlowGeometry = new THREE.SphereGeometry(2.1, 32, 32); | |
| const sunGlowMaterial = new THREE.MeshBasicMaterial({ | |
| color: 0xffd700, | |
| transparent: true, | |
| opacity: 0.3, | |
| blending: THREE.AdditiveBlending | |
| }); | |
| const sunGlow = new THREE.Mesh(sunGlowGeometry, sunGlowMaterial); | |
| scene.add(sunGlow); | |
| // Create planets | |
| const planets = []; | |
| let planetMeshes = []; | |
| planetsData.forEach((planet, index) => { | |
| const geometry = new THREE.SphereGeometry(planet.radius, 32, 32); | |
| const material = new THREE.MeshPhongMaterial({ | |
| color: planet.color, | |
| shininess: 5 | |
| }); | |
| const planetMesh = new THREE.Mesh(geometry, material); | |
| // Position planet in orbit | |
| const angle = (index / planetsData.length) * Math.PI * 2; | |
| planetMesh.position.x = planet.distance * Math.cos(angle); | |
| planetMesh.position.z = planet.distance * Math.sin(angle); | |
| // Store additional properties | |
| planetMesh.userData = { | |
| ...planet, | |
| originalDistance: planet.distance, | |
| originalSpeed: planet.speed, | |
| currentAngle: angle | |
| }; | |
| scene.add(planetMesh); | |
| planetMeshes.push(planetMesh); | |
| // Add orbital path | |
| const orbitGeometry = new THREE.BufferGeometry(); | |
| const orbitMaterial = new THREE.LineBasicMaterial({ | |
| color: 0x666666, | |
| transparent: true, | |
| opacity: 0.3 | |
| }); | |
| const orbitPoints = []; | |
| for (let i = 0; i <= 64; i++) { | |
| const theta = (i / 64) * Math.PI * 2; | |
| orbitPoints.push(new THREE.Vector3( | |
| planet.distance * Math.cos(theta), | |
| 0, | |
| planet.distance * Math.sin(theta) | |
| )); | |
| } | |
| orbitGeometry.setFromPoints(orbitPoints); | |
| const orbit = new THREE.Line(orbitGeometry, orbitMaterial); | |
| scene.add(orbit); | |
| }); | |
| // Variables for animation control | |
| let speedFactor = 1; | |
| let animationId = null; | |
| const raycaster = new THREE.Raycaster(); | |
| const mouse = new THREE.Vector2(); | |
| let currentPlanet = null; | |
| // Handle planet clicks | |
| window.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(planetMeshes); | |
| if (intersects.length > 0) { | |
| const planet = intersects[0].object; | |
| currentPlanet = planet; | |
| // Show planet info | |
| document.getElementById('planetName').textContent = planet.userData.name; | |
| document.getElementById('planetType').textContent = planet.userData.type; | |
| document.getElementById('planetDiameter').textContent = planet.userData.diameter; | |
| document.getElementById('planetDistance').textContent = planet.userData.originalDistance.toFixed(1) + ' AU'; | |
| document.getElementById('planetPeriod').textContent = planet.userData.orbitalPeriod; | |
| document.getElementById('planetMoons').textContent = planet.userData.moons; | |
| document.getElementById('planetFact').textContent = planet.userData.fact; | |
| document.getElementById('planetInfo').style.display = 'block'; | |
| // Move camera to focus on planet | |
| const distanceToPlanet = planet.position.distanceTo(camera.position); | |
| controls.target.copy(planet.position); | |
| camera.position | |
| .copy(planet.position) | |
| .add(new THREE.Vector3(0, distanceToPlanet * 0.3, distanceToPlanet * 1.5)); | |
| } | |
| }); | |
| // Control buttons | |
| document.getElementById('speedUp').addEventListener('click', () => { | |
| speedFactor *= 1.5; | |
| }); | |
| document.getElementById('speedDown').addEventListener('click', () => { | |
| speedFactor /= 1.5; | |
| }); | |
| document.getElementById('zoomIn').addEventListener('click', () => { | |
| camera.position.multiplyScalar(0.9); | |
| }); | |
| document.getElementById('zoomOut').addEventListener('click', () => { | |
| camera.position.multiplyScalar(1.1); | |
| }); | |
| document.getElementById('resetView').addEventListener('click', () => { | |
| camera.position.set(0, 0, 30); | |
| controls.target.set(0, 0, 0); | |
| speedFactor = 1; | |
| }); | |
| // Handle window resize | |
| window.addEventListener('resize', () => { | |
| camera.aspect = container.clientWidth / container.clientHeight; | |
| camera.updateProjectionMatrix(); | |
| renderer.setSize(container.clientWidth, container.clientHeight); | |
| }); | |
| // Animation loop | |
| function animate() { | |
| animationId = requestAnimationFrame(animate); | |
| // Update sun glow animation | |
| sunGlow.scale.x = 1 + Math.sin(Date.now() * 0.001) * 0.05; | |
| sunGlow.scale.y = 1 + Math.cos(Date.now() * 0.001 + 0.5) * 0.05; | |
| sunGlow.scale.z = 1 + Math.sin(Date.now() * 0.001 + 1) * 0.05; | |
| // Rotate sun | |
| sun.rotation.y += 0.002; | |
| // Update planet positions | |
| planetMeshes.forEach(planet => { | |
| const data = planet.userData; | |
| data.currentAngle += data.speed * speedFactor; | |
| planet.position.x = data.originalDistance * Math.cos(data.currentAngle); | |
| planet.position.z = data.originalDistance * Math.sin(data.currentAngle); | |
| // Rotate planet | |
| planet.rotation.y += 0.01; | |
| }); | |
| controls.update(); | |
| renderer.render(scene, camera); | |
| } | |
| animate(); | |
| // Clean up on unmount | |
| window.addEventListener('beforeunload', () => { | |
| if (animationId) { | |
| cancelAnimationFrame(animationId); | |
| } | |
| renderer.dispose(); | |
| }); | |
| } | |
| </script> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <a href="https://enzostvs-deepsite.hf.space" style="color: #fff;" target="_blank" >DeepSite</a> <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;"></p></body> | |
| </html> |