solor-system-explorer / index.html
DK9's picture
Add 2 files
b9c314d verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Solar System Explorer with Textures</title>
<script src="https://cdn.tailwindcss.com"></script>
<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>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
<style>
.planet-info-card {
backdrop-filter: blur(10px);
background-color: rgba(15, 23, 42, 0.7);
border: 1px solid rgba(255, 255, 255, 0.1);
}
.ring {
position: absolute;
border: 2px solid rgba(255, 255, 255, 0.4);
border-radius: 50%;
transform: rotateX(75deg);
pointer-events: none;
}
#loading-screen {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #0f172a;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 9999;
transition: opacity 0.5s ease-out;
}
.loading-spinner {
width: 50px;
height: 50px;
border: 5px solid rgba(255, 255, 255, 0.3);
border-radius: 50%;
border-top-color: #3b82f6;
animation: spin 1s ease-in-out infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
#canvas-container {
transition: filter 0.3s ease;
}
.blur-effect {
filter: blur(4px);
}
</style>
</head>
<body class="bg-slate-900 text-slate-100 overflow-hidden">
<!-- Loading Screen -->
<div id="loading-screen">
<div class="loading-spinner mb-4"></div>
<p class="text-xl font-semibold">Loading the cosmos...</p>
<p class="text-slate-400 mt-2">Preparing your interstellar journey</p>
</div>
<div class="flex h-screen">
<!-- Sidebar -->
<div class="w-80 bg-slate-800/50 border-r border-slate-700/50 flex flex-col">
<div class="p-4 border-b border-slate-700/50">
<h1 class="text-2xl font-bold text-blue-400 flex items-center">
<i class="fas fa-globe-europe mr-2"></i>
Solar System Explorer
</h1>
<p class="text-slate-400 text-sm mt-1">Explore our cosmic neighborhood in 3D</p>
</div>
<div class="flex-1 overflow-y-auto p-4 space-y-4">
<div class="space-y-2">
<h2 class="text-lg font-semibold text-slate-300 flex items-center">
<i class="fas fa-sun mr-2 text-yellow-400"></i>
The Sun
</h2>
<button onclick="focusOnPlanet('sun')" class="w-full p-2 bg-slate-700/50 hover:bg-slate-700 rounded-lg text-left flex items-center">
<div class="w-6 h-6 rounded-full bg-yellow-500 mr-3"></div>
View the Sun
</button>
</div>
<div class="space-y-2">
<h2 class="text-lg font-semibold text-slate-300 flex items-center">
<i class="fas fa-globe-americas mr-2 text-blue-400"></i>
Rocky Planets
</h2>
<button onclick="focusOnPlanet('mercury')" class="w-full p-2 bg-slate-700/50 hover:bg-slate-700 rounded-lg text-left flex items-center">
<div class="w-6 h-6 rounded-full bg-gray-400 mr-3"></div>
Mercury
</button>
<button onclick="focusOnPlanet('venus')" class="w-full p-2 bg-slate-700/50 hover:bg-slate-700 rounded-lg text-left flex items-center">
<div class="w-6 h-6 rounded-full bg-yellow-200 mr-3"></div>
Venus
</button>
<button onclick="focusOnPlanet('earth')" class="w-full p-2 bg-slate-700/50 hover:bg-slate-700 rounded-lg text-left flex items-center">
<div class="w-6 h-6 rounded-full bg-blue-500 mr-3"></div>
Earth
</button>
<button onclick="focusOnPlanet('mars')" class="w-full p-2 bg-slate-700/50 hover:bg-slate-700 rounded-lg text-left flex items-center">
<div class="w-6 h-6 rounded-full bg-red-500 mr-3"></div>
Mars
</button>
</div>
<div class="space-y-2">
<h2 class="text-lg font-semibold text-slate-300 flex items-center">
<i class="fas fa-ring mr-2 text-purple-400"></i>
Gas Giants
</h2>
<button onclick="focusOnPlanet('jupiter')" class="w-full p-2 bg-slate-700/50 hover:bg-slate-700 rounded-lg text-left flex items-center">
<div class="w-6 h-6 rounded-full bg-yellow-300 mr-3"></div>
Jupiter
</button>
<button onclick="focusOnPlanet('saturn')" class="w-full p-2 bg-slate-700/50 hover:bg-slate-700 rounded-lg text-left flex items-center">
<div class="w-6 h-6 rounded-full bg-yellow-200 mr-3 relative">
<div class="ring" style="width: 16px; height: 16px; top: -3px; left: -3px;"></div>
</div>
Saturn
</button>
<button onclick="focusOnPlanet('uranus')" class="w-full p-2 bg-slate-700/50 hover:bg-slate-700 rounded-lg text-left flex items-center">
<div class="w-6 h-6 rounded-full bg-teal-300 mr-3"></div>
Uranus
</button>
<button onclick="focusOnPlanet('neptune')" class="w-full p-2 bg-slate-700/50 hover:bg-slate-700 rounded-lg text-left flex items-center">
<div class="w-6 h-6 rounded-full bg-blue-400 mr-3"></div>
Neptune
</button>
</div>
<div class="space-y-2">
<h2 class="text-lg font-semibold text-slate-300 flex items-center">
<i class="fas fa-star mr-2 text-slate-400"></i>
Dwarf Planets
</h2>
<button onclick="focusOnPlanet('pluto')" class="w-full p-2 bg-slate-700/50 hover:bg-slate-700 rounded-lg text-left flex items-center">
<div class="w-6 h-6 rounded-full bg-gray-300 mr-3"></div>
Pluto
</button>
</div>
</div>
<div class="p-4 border-t border-slate-700/50 text-sm text-slate-400">
<p>Use mouse to rotate, scroll to zoom</p>
<p class="mt-1">Hold right click to pan</p>
</div>
</div>
<!-- Main Content -->
<div class="flex-1 relative">
<div id="canvas-container" class="h-full w-full">
<!-- Three.js canvas will be inserted here -->
</div>
<!-- Planet Info Card -->
<div id="planet-info" class="planet-info-card absolute top-4 right-4 p-4 rounded-lg shadow-lg w-64 hidden">
<div class="flex justify-between items-start">
<div>
<h2 id="planet-name" class="text-xl font-bold"></h2>
<p id="planet-type" class="text-sm text-slate-300"></p>
</div>
<button onclick="hidePlanetInfo()" class="text-slate-400 hover:text-white">
<i class="fas fa-times"></i>
</button>
</div>
<div class="mt-4 space-y-3">
<div>
<p class="text-xs text-slate-400">Distance from Sun</p>
<p id="planet-distance" class="text-sm"></p>
</div>
<div>
<p class="text-xs text-slate-400">Diameter</p>
<p id="planet-diameter" class="text-sm"></p>
</div>
<div>
<p class="text-xs text-slate-400">Orbital Period</p>
<p id="planet-period" class="text-sm"></p>
</div>
<div>
<p class="text-xs text-slate-400">Surface Temperature</p>
<p id="planet-temperature" class="text-sm"></p>
</div>
</div>
<div class="mt-4 pt-3 border-t border-slate-700/50">
<p id="planet-fact" class="text-sm italic text-slate-300"></p>
</div>
</div>
<!-- Controls -->
<div class="absolute bottom-4 left-1/2 transform -translate-x-1/2 flex space-x-2">
<button onclick="toggleAutoRotate()" id="auto-rotate-btn" class="bg-slate-800/70 hover:bg-slate-700/70 p-2 rounded-full">
<i class="fas fa-sync-alt"></i>
</button>
<button onclick="resetCamera()" class="bg-slate-800/70 hover:bg-slate-700/70 p-2 rounded-full">
<i class="fas fa-home"></i>
</button>
<button onclick="toggleFullscreen()" class="bg-slate-800/70 hover:bg-slate-700/70 p-2 rounded-full">
<i class="fas fa-expand"></i>
</button>
</div>
<!-- Current Planet Indicator -->
<div id="current-planet-indicator" class="absolute top-4 left-4 bg-slate-800/70 px-3 py-1 rounded-full text-sm hidden">
Viewing: <span id="current-planet-name" class="font-semibold"></span>
</div>
</div>
</div>
<script>
// Three.js variables
let scene, camera, renderer, controls;
let planets = {};
let currentPlanet = null;
let autoRotate = true;
let planetMeshes = {};
let textureLoader = new THREE.TextureLoader();
let loadingManager = new THREE.LoadingManager();
// Planet data with texture URLs
const planetInfo = {
sun: {
name: "The Sun",
type: "Yellow Dwarf Star",
distance: "0 km (Center of Solar System)",
diameter: "1,392,700 km",
period: "N/A",
temperature: "5,500°C (Surface)",
fact: "The Sun contains 99.86% of the mass in the Solar System.",
textureUrl: "https://www.solarsystemscope.com/textures/download/2k_sun.jpg",
size: 10,
position: { x: 0, y: 0, z: 0 }
},
mercury: {
name: "Mercury",
type: "Terrestrial Planet",
distance: "57.9 million km",
diameter: "4,880 km",
period: "88 Earth days",
temperature: "-173°C to 427°C",
fact: "A day on Mercury (sunrise to sunrise) lasts 176 Earth days.",
textureUrl: "https://www.solarsystemscope.com/textures/download/2k_mercury.jpg",
size: 0.8,
position: { x: 20, y: 0, z: 0 }
},
venus: {
name: "Venus",
type: "Terrestrial Planet",
distance: "108.2 million km",
diameter: "12,104 km",
period: "225 Earth days",
temperature: "462°C (Average)",
fact: "Venus rotates in the opposite direction to most planets.",
textureUrl: "https://www.solarsystemscope.com/textures/download/2k_venus_surface.jpg",
size: 0.95,
position: { x: 30, y: 0, z: 0 }
},
earth: {
name: "Earth",
type: "Terrestrial Planet",
distance: "149.6 million km",
diameter: "12,742 km",
period: "365.25 days",
temperature: "-88°C to 58°C",
fact: "Earth is the only known planet to support life.",
textureUrl: "https://www.solarsystemscope.com/textures/download/2k_earth_daymap.jpg",
size: 1,
position: { x: 40, y: 0, z: 0 }
},
mars: {
name: "Mars",
type: "Terrestrial Planet",
distance: "227.9 million km",
diameter: "6,779 km",
period: "687 Earth days",
temperature: "-140°C to 20°C",
fact: "Mars has the largest volcano in the solar system - Olympus Mons.",
textureUrl: "https://www.solarsystemscope.com/textures/download/2k_mars.jpg",
size: 0.53,
position: { x: 50, y: 0, z: 0 }
},
jupiter: {
name: "Jupiter",
type: "Gas Giant",
distance: "778.5 million km",
diameter: "139,820 km",
period: "11.86 Earth years",
temperature: "-145°C (Cloud tops)",
fact: "Jupiter's Great Red Spot is a storm that has raged for at least 400 years.",
textureUrl: "https://www.solarsystemscope.com/textures/download/2k_jupiter.jpg",
size: 2.5,
position: { x: 70, y: 0, z: 0 }
},
saturn: {
name: "Saturn",
type: "Gas Giant",
distance: "1.43 billion km",
diameter: "116,460 km",
period: "29.46 Earth years",
temperature: "-178°C (Cloud tops)",
fact: "Saturn's rings are made mostly of chunks of ice and rock.",
textureUrl: "https://www.solarsystemscope.com/textures/download/2k_saturn.jpg",
ringTextureUrl: "https://www.solarsystemscope.com/textures/download/2k_saturn_ring_alpha.png",
size: 2,
position: { x: 90, y: 0, z: 0 }
},
uranus: {
name: "Uranus",
type: "Ice Giant",
distance: "2.87 billion km",
diameter: "50,724 km",
period: "84 Earth years",
temperature: "-216°C (Cloud tops)",
fact: "Uranus rotates on its side, with an axial tilt of 98 degrees.",
textureUrl: "https://www.solarsystemscope.com/textures/download/2k_uranus.jpg",
ringTextureUrl: "https://www.solarsystemscope.com/textures/download/2k_uranus_ring.png",
size: 1.5,
position: { x: 110, y: 0, z: 0 }
},
neptune: {
name: "Neptune",
type: "Ice Giant",
distance: "4.5 billion km",
diameter: "49,244 km",
period: "164.8 Earth years",
temperature: "-214°C (Cloud tops)",
fact: "Neptune has the strongest winds in the solar system, up to 2,100 km/h.",
textureUrl: "https://www.solarsystemscope.com/textures/download/2k_neptune.jpg",
size: 1.5,
position: { x: 130, y: 0, z: 0 }
},
pluto: {
name: "Pluto",
type: "Dwarf Planet",
distance: "5.9 billion km",
diameter: "2,377 km",
period: "248 Earth years",
temperature: "-233°C to -223°C",
fact: "Pluto was reclassified as a dwarf planet in 2006.",
textureUrl: "https://www.solarsystemscope.com/textures/download/2k_pluto.jpg",
size: 0.3,
position: { x: 150, y: 0, z: 0 }
}
};
// Initialize Three.js scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x0f172a);
// Add ambient light
const ambientLight = new THREE.AmbientLight(0x404040);
scene.add(ambientLight);
// Add directional light (sun)
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(0, 0, 0);
scene.add(directionalLight);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 20, 50);
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.getElementById('canvas-container').appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.autoRotate = autoRotate;
controls.autoRotateSpeed = 0.5;
// Create planets with textures
createPlanetsWithTextures();
// Add stars background
addStars();
// Start with Earth focused
setTimeout(() => {
focusOnPlanet('earth');
hideLoadingScreen();
}, 1500);
// Handle window resize
window.addEventListener('resize', onWindowResize);
// Start animation loop
animate();
}
// Create all planets with textures
function createPlanetsWithTextures() {
// Create the Sun with texture
const sunGeometry = new THREE.SphereGeometry(planetInfo.sun.size, 64, 64);
const sunMaterial = new THREE.MeshBasicMaterial({
color: 0xffff00,
emissive: 0xffffbb,
emissiveIntensity: 1
});
const sun = new THREE.Mesh(sunGeometry, sunMaterial);
sun.position.set(0, 0, 0);
scene.add(sun);
planetMeshes.sun = sun;
// Load sun texture
textureLoader.load(planetInfo.sun.textureUrl, function(texture) {
sunMaterial.map = texture;
sunMaterial.needsUpdate = true;
});
// Create other planets with placeholder colors first
for (const planet in planetInfo) {
if (planet === 'sun') continue;
const geometry = new THREE.SphereGeometry(planetInfo[planet].size, 64, 64);
let material;
// Set placeholder colors based on planet type
if (planet === 'mercury') material = new THREE.MeshPhongMaterial({ color: 0xaaaaaa });
else if (planet === 'venus') material = new THREE.MeshPhongMaterial({ color: 0xffccaa });
else if (planet === 'earth') material = new THREE.MeshPhongMaterial({ color: 0x1a66ff });
else if (planet === 'mars') material = new THREE.MeshPhongMaterial({ color: 0xff3300 });
else if (planet === 'jupiter') material = new THREE.MeshPhongMaterial({ color: 0xffcc99 });
else if (planet === 'saturn') material = new THREE.MeshPhongMaterial({ color: 0xffdd99 });
else if (planet === 'uranus') material = new THREE.MeshPhongMaterial({ color: 0x99ffff });
else if (planet === 'neptune') material = new THREE.MeshPhongMaterial({ color: 0x3399ff });
else if (planet === 'pluto') material = new THREE.MeshPhongMaterial({ color: 0xcccccc });
const planetMesh = new THREE.Mesh(geometry, material);
// Position the planet
planetMesh.position.set(
planetInfo[planet].position.x,
planetInfo[planet].position.y,
planetInfo[planet].position.z
);
scene.add(planetMesh);
planetMeshes[planet] = planetMesh;
// Load actual textures
textureLoader.load(planetInfo[planet].textureUrl, function(texture) {
material.map = texture;
material.needsUpdate = true;
// Add rings to Saturn
if (planet === 'saturn') {
textureLoader.load(planetInfo.saturn.ringTextureUrl, function(ringTexture) {
const ringGeometry = new THREE.RingGeometry(2.2, 3.5, 64);
const ringMaterial = new THREE.MeshPhongMaterial({
map: ringTexture,
side: THREE.DoubleSide,
transparent: true,
opacity: 0.8
});
const ring = new THREE.Mesh(ringGeometry, ringMaterial);
ring.rotation.x = Math.PI / 2;
planetMesh.add(ring);
});
}
// Add rings to Uranus
if (planet === 'uranus') {
textureLoader.load(planetInfo.uranus.ringTextureUrl, function(ringTexture) {
const ringGeometry = new THREE.RingGeometry(1.8, 2.5, 64);
const ringMaterial = new THREE.MeshPhongMaterial({
map: ringTexture,
side: THREE.DoubleSide,
transparent: true,
opacity: 0.6
});
const ring = new THREE.Mesh(ringGeometry, ringMaterial);
ring.rotation.x = Math.PI / 2;
planetMesh.add(ring);
});
}
});
}
}
// Add stars background
function addStars() {
const starsGeometry = new THREE.BufferGeometry();
const starCount = 5000;
const positions = new Float32Array(starCount * 3);
for (let i = 0; i < starCount; i++) {
const i3 = i * 3;
positions[i3] = (Math.random() - 0.5) * 2000;
positions[i3 + 1] = (Math.random() - 0.5) * 2000;
positions[i3 + 2] = (Math.random() - 0.5) * 2000;
}
starsGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
const starsMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 0.5,
transparent: true,
opacity: 0.8
});
const stars = new THREE.Points(starsGeometry, starsMaterial);
scene.add(stars);
}
// Focus camera on a specific planet
function focusOnPlanet(planetName) {
if (!planetMeshes[planetName]) return;
currentPlanet = planetName;
const planet = planetMeshes[planetName];
const planetData = planetInfo[planetName];
// Calculate target position (slightly above the planet)
const targetPosition = new THREE.Vector3(
planet.position.x,
planet.position.y + planetData.size * 0.5,
planet.position.z
);
// Calculate camera position based on planet size
const distance = planetData.size * 5;
const cameraPosition = new THREE.Vector3(
planet.position.x,
planet.position.y + planetData.size * 0.5,
planet.position.z + distance
);
// Animate camera movement
const duration = 1000;
const startTime = Date.now();
const animateCamera = () => {
const elapsed = Date.now() - startTime;
const progress = Math.min(elapsed / duration, 1);
// Ease in-out function
const easeProgress = progress < 0.5
? 2 * progress * progress
: 1 - Math.pow(-2 * progress + 2, 2) / 2;
// Interpolate positions
camera.position.lerpVectors(
camera.position,
cameraPosition,
easeProgress
);
controls.target.lerpVectors(
controls.target,
targetPosition,
easeProgress
);
if (progress < 1) {
requestAnimationFrame(animateCamera);
} else {
// Update UI after animation completes
updatePlanetUI(planetName);
}
};
animateCamera();
}
// Update planet information UI
function updatePlanetUI(planetName) {
const planetData = planetInfo[planetName];
document.getElementById('planet-name').textContent = planetData.name;
document.getElementById('planet-type').textContent = planetData.type;
document.getElementById('planet-distance').textContent = planetData.distance;
document.getElementById('planet-diameter').textContent = planetData.diameter;
document.getElementById('planet-period').textContent = planetData.period;
document.getElementById('planet-temperature').textContent = planetData.temperature;
document.getElementById('planet-fact').textContent = planetData.fact;
// Show planet info card
document.getElementById('planet-info').classList.remove('hidden');
// Update current planet indicator
document.getElementById('current-planet-name').textContent = planetData.name;
document.getElementById('current-planet-indicator').classList.remove('hidden');
// Add blur effect to canvas
document.getElementById('canvas-container').classList.add('blur-effect');
}
// Hide planet information UI
function hidePlanetInfo() {
document.getElementById('planet-info').classList.add('hidden');
document.getElementById('canvas-container').classList.remove('blur-effect');
}
// Toggle auto-rotation
function toggleAutoRotate() {
autoRotate = !autoRotate;
controls.autoRotate = autoRotate;
const btn = document.getElementById('auto-rotate-btn');
if (autoRotate) {
btn.classList.remove('bg-slate-700/70');
btn.classList.add('bg-blue-600/70');
} else {
btn.classList.remove('bg-blue-600/70');
btn.classList.add('bg-slate-700/70');
}
}
// Reset camera to default position
function resetCamera() {
camera.position.set(0, 20, 50);
controls.target.set(0, 0, 0);
currentPlanet = null;
// Hide planet info
document.getElementById('planet-info').classList.add('hidden');
document.getElementById('current-planet-indicator').classList.add('hidden');
document.getElementById('canvas-container').classList.remove('blur-effect');
}
// Toggle fullscreen mode
function toggleFullscreen() {
if (!document.fullscreenElement) {
document.documentElement.requestFullscreen();
} else {
if (document.exitFullscreen) {
document.exitFullscreen();
}
}
}
// Hide loading screen
function hideLoadingScreen() {
const loadingScreen = document.getElementById('loading-screen');
loadingScreen.style.opacity = '0';
setTimeout(() => {
loadingScreen.style.display = 'none';
}, 500);
}
// Handle window resize
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
// Rotate planets
for (const planet in planetMeshes) {
if (planet === 'sun') continue;
// Each planet rotates at a different speed
let rotationSpeed = 0.005;
if (planet === 'mercury') rotationSpeed = 0.01;
if (planet === 'venus') rotationSpeed = -0.003; // Venus rotates backwards
if (planet === 'earth') rotationSpeed = 0.01;
if (planet === 'mars') rotationSpeed = 0.008;
if (planet === 'jupiter') rotationSpeed = 0.02;
if (planet === 'saturn') rotationSpeed = 0.015;
if (planet === 'uranus') rotationSpeed = -0.01; // Uranus rotates on its side
if (planet === 'neptune') rotationSpeed = 0.01;
if (planet === 'pluto') rotationSpeed = 0.005;
planetMeshes[planet].rotation.y += rotationSpeed;
}
// Required for damping
controls.update();
renderer.render(scene, camera);
}
// Initialize the app when the page loads
window.onload = init;
</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 <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=DK9/solor-system-explorer" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>