Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Interactive Solar System</title> | |
<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.min.js"></script> | |
<style> | |
* { | |
margin: 0; | |
padding: 0; | |
box-sizing: border-box; | |
} | |
body { | |
overflow: hidden; | |
background: #000; | |
font-family: 'Arial', sans-serif; | |
} | |
#canvas-container { | |
position: fixed; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
} | |
.controls { | |
position: absolute; | |
bottom: 30px; | |
left: 50%; | |
transform: translateX(-50%); | |
display: flex; | |
gap: 20px; | |
background: rgba(0, 0, 0, 0.7); | |
padding: 15px 25px; | |
border-radius: 50px; | |
backdrop-filter: blur(10px); | |
border: 1px solid rgba(255, 255, 255, 0.1); | |
} | |
.control-btn { | |
background: linear-gradient(45deg, #4a00e0, #8e2de2); | |
border: none; | |
color: white; | |
width: 50px; | |
height: 50px; | |
border-radius: 50%; | |
cursor: pointer; | |
font-size: 18px; | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
transition: all 0.3s ease; | |
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3); | |
} | |
.control-btn:hover { | |
transform: scale(1.1); | |
box-shadow: 0 8px 25px rgba(142, 45, 226, 0.4); | |
} | |
.speed-control { | |
display: flex; | |
align-items: center; | |
gap: 15px; | |
color: white; | |
} | |
.speed-slider { | |
width: 200px; | |
height: 6px; | |
-webkit-appearance: none; | |
background: linear-gradient(to right, #4a00e0, #8e2de2); | |
border-radius: 3px; | |
outline: none; | |
} | |
.speed-slider::-webkit-slider-thumb { | |
-webkit-appearance: none; | |
width: 20px; | |
height: 20px; | |
border-radius: 50%; | |
background: white; | |
cursor: pointer; | |
box-shadow: 0 0 10px rgba(142, 45, 226, 0.8); | |
} | |
.info-panel { | |
position: absolute; | |
top: 30px; | |
right: 30px; | |
width: 320px; | |
background: rgba(0, 0, 0, 0.85); | |
backdrop-filter: blur(20px); | |
border-radius: 20px; | |
padding: 25px; | |
color: white; | |
border: 1px solid rgba(255, 255, 255, 0.1); | |
box-shadow: 0 20px 50px rgba(0, 0, 0, 0.5); | |
transform: translateX(120%); | |
transition: transform 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55); | |
z-index: 100; | |
} | |
.info-panel.visible { | |
transform: translateX(0); | |
} | |
.info-header { | |
display: flex; | |
align-items: center; | |
margin-bottom: 20px; | |
} | |
.planet-icon { | |
width: 50px; | |
height: 50px; | |
border-radius: 50%; | |
margin-right: 15px; | |
background-size: cover; | |
} | |
.planet-name { | |
font-size: 24px; | |
font-weight: bold; | |
background: linear-gradient(45deg, #4a00e0, #8e2de2); | |
-webkit-background-clip: text; | |
-webkit-text-fill-color: transparent; | |
} | |
.info-content { | |
line-height: 1.6; | |
} | |
.info-item { | |
margin-bottom: 15px; | |
padding-bottom: 15px; | |
border-bottom: 1px solid rgba(255, 255, 255, 0.1); | |
} | |
.info-label { | |
color: #8e2de2; | |
font-weight: bold; | |
margin-bottom: 5px; | |
} | |
.info-value { | |
color: white; | |
font-size: 16px; | |
} | |
.info-description { | |
color: #ccc; | |
font-size: 14px; | |
line-height: 1.5; | |
} | |
.close-btn { | |
position: absolute; | |
top: 15px; | |
right: 15px; | |
background: rgba(255, 255, 255, 0.1); | |
border: none; | |
color: white; | |
width: 30px; | |
height: 30px; | |
border-radius: 50%; | |
cursor: pointer; | |
font-size: 16px; | |
} | |
.title { | |
position: absolute; | |
top: 30px; | |
left: 30px; | |
color: white; | |
font-size: 28px; | |
font-weight: bold; | |
text-shadow: 0 0 20px rgba(142, 45, 226, 0.8); | |
} | |
.title span { | |
background: linear-gradient(45deg, #4a00e0, #8e2de2); | |
-webkit-background-clip: text; | |
-webkit-text-fill-color: transparent; | |
} | |
@media (max-width: 768px) { | |
.controls { | |
flex-direction: column; | |
border-radius: 20px; | |
padding: 15px; | |
} | |
.info-panel { | |
width: calc(100% - 40px); | |
right: 20px; | |
top: 20px; | |
} | |
.title { | |
font-size: 20px; | |
top: 15px; | |
left: 15px; | |
} | |
} | |
</style> | |
</head> | |
<body> | |
<div id="canvas-container"></div> | |
<div class="title">Interactive <span>Solar System</span></div> | |
<div class="controls"> | |
<button id="playPauseBtn" class="control-btn">βΈοΈ</button> | |
<div class="speed-control"> | |
<span>π’</span> | |
<input type="range" id="speedSlider" class="speed-slider" min="0" max="2" step="0.1" value="1"> | |
<span>π°</span> | |
</div> | |
</div> | |
<div id="infoPanel" class="info-panel"> | |
<button class="close-btn">Γ</button> | |
<div class="info-header"> | |
<div class="planet-icon" id="planetIcon"></div> | |
<div class="planet-name" id="planetName">Planet Name</div> | |
</div> | |
<div class="info-content"> | |
<div class="info-item"> | |
<div class="info-label">Distance from Sun</div> | |
<div class="info-value" id="distance">0 million km</div> | |
</div> | |
<div class="info-item"> | |
<div class="info-label">Orbital Period</div> | |
<div class="info-value" id="period">0 Earth days</div> | |
</div> | |
<div class="info-item"> | |
<div class="info-label">Description</div> | |
<div class="info-description" id="description">Planet description...</div> | |
</div> | |
</div> | |
</div> | |
<script> | |
// Planet data with realistic information | |
const planetData = [ | |
{ | |
name: "Mercury", | |
radius: 1.2, | |
distance: 20, | |
speed: 4.0, | |
rotationSpeed: 0.017, | |
color: 0x8a8a8a, | |
description: "The smallest planet in our solar system and closest to the Sun. Mercury has no atmosphere and experiences extreme temperature variations.", | |
distanceFromSun: 57.9, | |
orbitalPeriod: 88 | |
}, | |
{ | |
name: "Venus", | |
radius: 3.0, | |
distance: 30, | |
speed: 3.25, | |
rotationSpeed: 0.004, | |
color: 0xe39e1c, | |
description: "The hottest planet in our solar system with a thick toxic atmosphere. Venus is often called Earth's sister planet due to its similar size.", | |
distanceFromSun: 108.2, | |
orbitalPeriod: 225 | |
}, | |
{ | |
name: "Earth", | |
radius: 3.1, | |
distance: 40, | |
speed: 2.75, | |
rotationSpeed: 0.01, | |
color: 0x1f77b4, | |
description: "Our home planet and the only known place in the universe with life. Earth has a diverse biosphere and a protective atmosphere.", | |
distanceFromSun: 149.6, | |
orbitalPeriod: 365 | |
}, | |
{ | |
name: "Mars", | |
radius: 1.7, | |
distance: 50, | |
speed: 2.25, | |
rotationSpeed: 0.0097, | |
color: 0xff7f0e, | |
description: "The Red Planet known for its iron oxide surface. Mars has the largest volcano and canyon in the solar system.", | |
distanceFromSun: 227.9, | |
orbitalPeriod: 687 | |
}, | |
{ | |
name: "Jupiter", | |
radius: 10.0, | |
distance: 70, | |
speed: 1.25, | |
rotationSpeed: 0.024, | |
color: 0xd8ca9d, | |
description: "The largest planet in our solar system, a gas giant with a prominent Great Red Spot storm. Jupiter has at least 79 moons.", | |
distanceFromSun: 778.5, | |
orbitalPeriod: 4333 | |
}, | |
{ | |
name: "Saturn", | |
radius: 8.4, | |
distance: 90, | |
speed: 1.0, | |
rotationSpeed: 0.019, | |
color: 0xf0e0a0, | |
description: "Famous for its spectacular ring system made of ice and rock particles. Saturn is the least dense planet in our solar system.", | |
distanceFromSun: 1432.0, | |
orbitalPeriod: 10759 | |
}, | |
{ | |
name: "Uranus", | |
radius: 3.6, | |
distance: 110, | |
speed: 0.75, | |
rotationSpeed: 0.015, | |
color: 0xa0d0e0, | |
description: "An ice giant that rotates on its side, possibly due to an ancient collision. Uranus has a blue-green color due to methane in its atmosphere.", | |
distanceFromSun: 2867.0, | |
orbitalPeriod: 30687 | |
}, | |
{ | |
name: "Neptune", | |
radius: 3.5, | |
distance: 130, | |
speed: 0.6, | |
rotationSpeed: 0.018, | |
color: 0x4f79da, | |
description: "The windiest planet with speeds up to 2,100 km/h. Neptune was the first planet discovered through mathematical predictions.", | |
distanceFromSun: 4515.0, | |
orbitalPeriod: 60190 | |
} | |
]; | |
// Initialize Three.js | |
const scene = new THREE.Scene(); | |
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 3000); | |
const renderer = new THREE.WebGLRenderer({ antialias: true }); | |
renderer.setSize(window.innerWidth, window.innerHeight); | |
renderer.setPixelRatio(window.devicePixelRatio); | |
document.getElementById('canvas-container').appendChild(renderer.domElement); | |
// Add orbit controls | |
const controls = new THREE.OrbitControls(camera, renderer.domElement); | |
controls.enableDamping = true; | |
controls.dampingFactor = 0.05; | |
// Create stars background | |
const starsGeometry = new THREE.BufferGeometry(); | |
const starsMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 1 }); | |
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 starField = new THREE.Points(starsGeometry, starsMaterial); | |
scene.add(starField); | |
// Create the Sun | |
const sunGeometry = new THREE.SphereGeometry(10, 64, 64); | |
const sunMaterial = new THREE.MeshBasicMaterial({ | |
color: 0xffff00, | |
emissive: 0xffff33, | |
emissiveIntensity: 1 | |
}); | |
const sun = new THREE.Mesh(sunGeometry, sunMaterial); | |
scene.add(sun); | |
// Add sun glow effect | |
const sunGlowGeometry = new THREE.SphereGeometry(12, 32, 32); | |
const sunGlowMaterial = new THREE.MeshBasicMaterial({ | |
color: 0xffff00, | |
transparent: true, | |
opacity: 0.3 | |
}); | |
const sunGlow = new THREE.Mesh(sunGlowGeometry, sunGlowMaterial); | |
scene.add(sunGlow); | |
// Create planets | |
const planets = []; | |
const orbits = []; | |
planetData.forEach((planet, index) => { | |
// Create planet | |
const geometry = new THREE.SphereGeometry(planet.radius, 32, 32); | |
const material = new THREE.MeshLambertMaterial({ color: planet.color }); | |
const mesh = new THREE.Mesh(geometry, material); | |
// Position planet | |
const distance = planet.distance; // Scale down for visualization | |
mesh.position.x = distance; | |
// Create orbit path | |
const orbitGeometry = new THREE.BufferGeometry(); | |
const orbitPoints = []; | |
const orbitSegments = 128; | |
for (let i = 0; i <= orbitSegments; i++) { | |
const theta = (i / orbitSegments) * Math.PI * 2; | |
orbitPoints.push( | |
Math.cos(theta) * distance, | |
0, | |
Math.sin(theta) * distance | |
); | |
} | |
orbitGeometry.setAttribute('position', new THREE.Float32BufferAttribute(orbitPoints, 3)); | |
const orbitMaterial = new THREE.LineBasicMaterial({ | |
color: 0xffffff, | |
transparent: true, | |
opacity: 0.6 | |
}); | |
const orbit = new THREE.Line(orbitGeometry, orbitMaterial); | |
scene.add(orbit); | |
orbits.push(orbit); | |
// Add to scene | |
scene.add(mesh); | |
// Store planet data | |
planets.push({ | |
mesh: mesh, | |
data: planet, | |
angle: Math.random() * Math.PI * 2, | |
distance: distance, | |
speed: planet.speed * 0.05, | |
rotationSpeed: planet.rotationSpeed | |
}); | |
// Add rings to Saturn | |
if (planet.name === "Saturn") { | |
const ringGeometry = new THREE.RingGeometry(planet.radius * 1.5, planet.radius * 2.5, 64); | |
const ringMaterial = new THREE.MeshBasicMaterial({ | |
color: 0xf0e0a0, | |
side: THREE.DoubleSide, | |
transparent: true, | |
opacity: 0.8 | |
}); | |
const ring = new THREE.Mesh(ringGeometry, ringMaterial); | |
ring.rotation.x = Math.PI / 3; | |
mesh.add(ring); | |
} | |
}); | |
// Add ambient light | |
const ambientLight = new THREE.AmbientLight(0x333333); | |
scene.add(ambientLight); | |
// Add directional light (sunlight) | |
const sunLight = new THREE.PointLight(0xffffff, 1.5, 3000); | |
sunLight.position.set(0, 0, 0); | |
scene.add(sunLight); | |
// Position camera | |
camera.position.set(0, 100, 300); | |
controls.update(); | |
// UI Controls | |
let isPlaying = true; | |
let speed = 1; | |
const playPauseBtn = document.getElementById('playPauseBtn'); | |
const speedSlider = document.getElementById('speedSlider'); | |
const infoPanel = document.getElementById('infoPanel'); | |
const closeBtn = document.querySelector('.close-btn'); | |
playPauseBtn.addEventListener('click', () => { | |
isPlaying = !isPlaying; | |
playPauseBtn.textContent = isPlaying ? 'βΈοΈ' : 'βΆοΈ'; | |
}); | |
speedSlider.addEventListener('input', (e) => { | |
speed = parseFloat(e.target.value); | |
}); | |
closeBtn.addEventListener('click', () => { | |
infoPanel.classList.remove('visible'); | |
}); | |
// Raycaster for planet selection | |
const raycaster = new THREE.Raycaster(); | |
const mouse = new THREE.Vector2(); | |
function onMouseClick(event) { | |
// Calculate mouse position in normalized device coordinates | |
mouse.x = (event.clientX / window.innerWidth) * 2 - 1; | |
mouse.y = - (event.clientY / window.innerHeight) * 2 + 1; | |
// Update the picking ray with the camera and mouse position | |
raycaster.setFromCamera(mouse, camera); | |
// Calculate objects intersecting the picking ray | |
const intersects = raycaster.intersectObjects(planets.map(p => p.mesh)); | |
if (intersects.length > 0) { | |
const planetMesh = intersects[0].object; | |
const planet = planets.find(p => p.mesh === planetMesh); | |
if (planet) { | |
showPlanetInfo(planet.data); | |
} | |
} | |
} | |
function showPlanetInfo(planet) { | |
document.getElementById('planetName').textContent = planet.name; | |
document.getElementById('distance').textContent = `${planet.distanceFromSun} million km`; | |
document.getElementById('period').textContent = `${planet.orbitalPeriod} Earth days`; | |
document.getElementById('description').textContent = planet.description; | |
// Set planet icon color | |
const icon = document.getElementById('planetIcon'); | |
icon.style.backgroundColor = `#${planet.color.toString(16).padStart(6, '0')}`; | |
infoPanel.classList.add('visible'); | |
} | |
window.addEventListener('click', onMouseClick); | |
// Handle window resize | |
window.addEventListener('resize', () => { | |
camera.aspect = window.innerWidth / window.innerHeight; | |
camera.updateProjectionMatrix(); | |
renderer.setSize(window.innerWidth, window.innerHeight); | |
}); | |
// Animation loop | |
function animate() { | |
requestAnimationFrame(animate); | |
if (isPlaying) { | |
// Rotate sun | |
sun.rotation.y += 0.002 * speed; | |
sunGlow.rotation.y += 0.002 * speed; | |
// Update planets | |
planets.forEach(planet => { | |
// Orbit around sun | |
planet.angle += planet.speed * speed; | |
planet.mesh.position.x = Math.cos(planet.angle) * planet.distance; | |
planet.mesh.position.z = Math.sin(planet.angle) * planet.distance; | |
// Rotate on axis | |
planet.mesh.rotation.y += planet.rotationSpeed * speed; | |
}); | |
} | |
controls.update(); | |
renderer.render(scene, camera); | |
} | |
animate(); | |
</script> | |
</body> | |
</html> |