SaidAmchghal's picture
Exécuter ce code : <!DOCTYPE html>
f67a62b 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 Simulation</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
#scene-container {
width: 100vw;
height: 100vh;
position: relative;
overflow: hidden;
}
#planet-info {
display: none;
position: absolute;
bottom: 5vh;
left: 50%;
transform: translateX(-50%);
background: rgba(0,0,0,0.8);
backdrop-filter: blur(10px);
color: white;
padding: 1.5rem;
border-radius: 1rem;
max-width: 90%;
width: 500px;
box-sizing: border-box;
z-index: 1000;
box-shadow: 0 10px 25px rgba(0,0,0,0.5);
border: 1px solid rgba(255,255,255,0.1);
}
#planet-info h2 {
margin-top: 0;
font-size: 1.75rem;
color: #fff;
border-bottom: 1px solid rgba(255,255,255,0.2);
padding-bottom: 0.5rem;
margin-bottom: 1rem;
}
#planet-info p {
margin: 0.5rem 0;
line-height: 1.6;
}
#planet-info button {
margin-top: 1rem;
background: rgba(255,255,255,0.1);
color: white;
border: none;
padding: 0.5rem 1rem;
border-radius: 0.375rem;
cursor: pointer;
font-size: 0.875rem;
transition: all 0.3s ease;
width: 100%;
}
#planet-info button:hover {
background: rgba(255,255,255,0.2);
transform: translateY(-2px);
}
.loading-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #000;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 1001;
color: white;
}
.loading-spinner {
width: 50px;
height: 50px;
border: 5px solid rgba(255,255,255,0.1);
border-radius: 50%;
border-top-color: #fff;
animation: spin 1s ease-in-out infinite;
margin-bottom: 1rem;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.hud {
position: absolute;
top: 20px;
left: 20px;
z-index: 100;
color: white;
background: rgba(0,0,0,0.5);
padding: 10px 15px;
border-radius: 8px;
font-family: 'Arial', sans-serif;
}
</style>
</head>
<body class="bg-black overflow-hidden">
<div class="loading-overlay" id="loading">
<div class="loading-spinner"></div>
<div>Loading Solar System...</div>
</div>
<div id="scene-container"></div>
<div id="planet-info"></div>
<div class="hud">
<div class="text-xl font-bold mb-2">Solar System</div>
<div class="text-sm">Click on planets for info</div>
</div>
<!-- Three.js Libraries -->
<script src="https://cdn.jsdelivr.net/npm/three@0.155.0/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.155.0/examples/jsm/controls/OrbitControls.js"></script>
<script>
// Configuration
const earthRealRadius = 6371; // Earth radius (km)
const earthScaledRadius = 1; // Earth radius in scene
const scaleAU = 200; // 1 AU = 200 units
const simSpeed = 1000; // Simulation speed (1s sim = 1000s real)
const planetScale = earthScaledRadius / earthRealRadius;
// Planet data
const planets = [
{
name: "Mercury",
radius: 2440,
orbitAU: 0.39,
orbitalPeriod: 87.97,
rotationPeriod: 58.646,
texture: "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7e/Mercury_radar_topographic_map.jpg/1280px-Mercury_radar_topographic_map.jpg",
desc: "The closest planet to the Sun. It has a thin exosphere and extreme temperature variations."
},
{
name: "Venus",
radius: 6052,
orbitAU: 0.72,
orbitalPeriod: 224.7,
rotationPeriod: 243.01,
texture: "https://upload.wikimedia.org/wikipedia/commons/thumb/7/79/Venus_globe_renders_v1_0.jpg/1280px-Venus_globe_renders_v1_0.jpg",
desc: "Similar in size to Earth but with a thick CO₂ atmosphere creating a runaway greenhouse effect (462°C average)."
},
{
name: "Earth",
radius: 6371,
orbitAU: 1.0,
orbitalPeriod: 365.25,
rotationPeriod: 1.0,
texture: "https://threejs.org/examples/textures/earth_atmos_2048.jpg",
desc: "The only known planet with life. Has abundant liquid water and an oxygen-rich atmosphere."
},
{
name: "Mars",
radius: 3390,
orbitAU: 1.52,
orbitalPeriod: 686.98,
rotationPeriod: 1.025,
texture: "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3e/Mars_globe_renders_v1_0.jpg/1280px-Mars_globe_renders_v1_0.jpg",
desc: "The 'Red Planet' with polar ice caps and evidence of past liquid water."
},
{
name: "Jupiter",
radius: 69911,
orbitAU: 5.2,
orbitalPeriod: 4332.59,
rotationPeriod: 0.4135,
texture: "https://threejs.org/examples/textures/jupiter.jpg",
desc: "The largest planet - a gas giant with a Great Red Spot (persistent storm larger than Earth)."
},
{
name: "Saturn",
radius: 58232,
orbitAU: 9.5,
orbitalPeriod: 10759.22,
rotationPeriod: 0.444,
texture: "https://threejs.org/examples/textures/saturn.jpg",
desc: "Famous for its spectacular ring system composed of ice and rock particles."
},
{
name: "Uranus",
radius: 25362,
orbitAU: 19.2,
orbitalPeriod: 30588.8,
rotationPeriod: 0.7183,
texture: "https://threejs.org/examples/textures/uranus.jpg",
desc: "An ice giant that rotates on its side (98° axial tilt) with a pale blue hue from methane."
},
{
name: "Neptune",
radius: 24622,
orbitAU: 30.1,
orbitalPeriod: 60182.0,
rotationPeriod: 0.6685,
texture: "https://threejs.org/examples/textures/neptune.jpg",
desc: "The windiest planet with speeds up to 2,100 km/h - an ice giant with active weather."
}
];
// Initialize Three.js
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 10000);
camera.position.set(0, 500, 5000);
const renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x000000, 1);
document.getElementById('scene-container').appendChild(renderer.domElement);
// Enhanced lighting
const ambientLight = new THREE.HemisphereLight(0x8888ff, 0x333333, 0.8);
scene.add(ambientLight);
const dirLight = new THREE.DirectionalLight(0xffffff, 1);
dirLight.position.set(5000, 5000, 5000);
scene.add(dirLight);
// Add stars background
const starsGeometry = new THREE.BufferGeometry();
const starsMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1,
transparent: true,
opacity: 0.8
});
const starsVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 20000;
const y = (Math.random() - 0.5) * 20000;
const z = (Math.random() - 0.5) * 20000;
starsVertices.push(x, y, z);
}
starsGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starsVertices, 3));
const stars = new THREE.Points(starsGeometry, starsMaterial);
scene.add(stars);
// Camera controls
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.minDistance = 100;
controls.maxDistance = 10000;
controls.autoRotate = true;
controls.autoRotateSpeed = 0.5;
// Texture loading with error handling
const textureLoader = new THREE.TextureLoader();
let allTextures = [];
let loadErrors = 0;
function loadTextures(callback) {
loadErrors = 0;
allTextures = [];
const total = planets.length + 1; // 8 planets + Sun
let loaded = 0;
// Load Sun texture
textureLoader.load(
"https://upload.wikimedia.org/wikipedia/commons/thumb/4/43/Sun_rasterized_2017.jpg/1280px-Sun_rasterized_2017.jpg",
(texture) => {
allTextures.push({ type: "sun", texture });
loaded++;
checkComplete();
},
undefined,
(err) => {
console.error("Sun texture loading error:", err);
loadErrors++;
checkComplete();
}
);
// Load planet textures
planets.forEach(planet => {
textureLoader.load(
planet.texture,
(texture) => {
allTextures.push({ type: "planet", planet, texture });
loaded++;
checkComplete();
},
undefined,
(err) => {
console.error(`${planet.name} texture loading error:`, err);
loadErrors++;
checkComplete();
}
);
});
function checkComplete() {
if (loaded + loadErrors === total) {
if (loadErrors > 0) {
console.error(`Failed to load ${loadErrors} texture(s). Check URLs or your connection.`);
}
callback();
}
}
}
// Create Sun with glow effect
function createSun() {
const sunData = allTextures.find(t => t.type === "sun");
const sunRadius = 696340 * planetScale;
const sunGeo = new THREE.SphereGeometry(sunRadius, 64, 64);
const sunMat = new THREE.MeshStandardMaterial({
map: sunData.texture,
emissive: 0xffd700,
emissiveIntensity: 1,
roughness: 0.8
});
const sun = new THREE.Mesh(sunGeo, sunMat);
// Add sun glow effect
const glowGeometry = new THREE.SphereGeometry(sunRadius * 1.2, 32, 32);
const glowMaterial = new THREE.MeshBasicMaterial({
color: 0xffd700,
transparent: true,
opacity: 0.3,
blending: THREE.AdditiveBlending
});
const glow = new THREE.Mesh(glowGeometry, glowMaterial);
sun.add(glow);
scene.add(sun);
return sun;
}
// Create planet with orbit
function createPlanet(planet, texture) {
const scaledRadius = planet.radius * planetScale;
const orbitRadius = planet.orbitAU * scaleAU;
// Calculate speeds
const rotSpeed = (Math.PI * 2) / (planet.rotationPeriod * 86400) * simSpeed;
const orbSpeed = (Math.PI * 2) / (planet.orbitalPeriod * 86400) * simSpeed;
// Planet geometry
const geo = new THREE.SphereGeometry(scaledRadius, 64, 64);
const mat = new THREE.MeshStandardMaterial({
map: texture,
roughness: 0.8,
metalness: 0.1
});
const mesh = new THREE.Mesh(geo, mat);
// User data for click detection
mesh.userData = {
type: "planet",
name: planet.name,
diameter: `${(2 * planet.radius).toLocaleString()} km`,
distance: `${planet.orbitAU.toFixed(2)} AU`,
period: `${planet.orbitalPeriod.toFixed(1)} days`,
rotationSpeed: rotSpeed,
orbitSpeed: orbSpeed,
orbitRadius: orbitRadius,
angle: Math.random() * Math.PI * 2, // Random start position
rotationAngle: 0,
desc: planet.desc
};
// Create orbit path
const orbitGeo = new THREE.CircleGeometry(orbitRadius, 200);
orbitGeo.rotateX(Math.PI / 2);
const orbitMat = new THREE.LineBasicMaterial({
color: 0x4a5568,
transparent: true,
opacity: 0.5
});
const orbitMesh = new THREE.LineLoop(orbitGeo, orbitMat);
scene.add(orbitMesh);
// Initial position
mesh.position.x = orbitRadius;
scene.add(mesh);
return { mesh, data: mesh.userData };
}
// Initialize scene after loading textures
loadTextures(() => {
document.getElementById('loading').style.display = 'none';
if (loadErrors === 0) {
createSun();
const planetObjects = [];
allTextures.forEach(t => {
if (t.type === "planet") {
const obj = createPlanet(t.planet, t.texture);
planetObjects.push(obj);
}
});
// Animation
const clock = new THREE.Clock();
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
controls.update(delta);
// Update planets
planetObjects.forEach(obj => {
const data = obj.data;
// Rotation
data.rotationAngle += data.rotationSpeed * delta;
obj.mesh.rotation.y = data.rotationAngle % (Math.PI * 2);
// Orbit
data.angle += data.orbitSpeed * delta;
const x = data.orbitRadius * Math.cos(data.angle);
const z = data.orbitRadius * Math.sin(data.angle);
obj.mesh.position.set(x, 0, z);
});
renderer.render(scene, camera);
}
animate();
// Window resize handler
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
}
// Planet click handler
const infoDiv = document.getElementById('planet-info');
renderer.domElement.addEventListener('click', (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 intersects = raycaster.intersectObjects(scene.children, true);
const clickedPlanet = intersects.find(inter => inter.object.userData?.type === "planet");
if (clickedPlanet && clickedPlanet.object.userData) {
const data = clickedPlanet.object.userData;
infoDiv.innerHTML = `
<h2>${data.name}</h2>
<p><strong>Diameter:</strong> ${data.diameter}</p>
<p><strong>Distance from Sun:</strong> ${data.distance}</p>
<p><strong>Orbital Period:</strong> ${data.period}</p>
<p>${data.desc}</p>
<button onclick="document.getElementById('planet-info').style.display = 'none'">Close</button>
`;
infoDiv.style.display = "block";
// Auto-hide after 10 seconds
setTimeout(() => {
infoDiv.style.display = "none";
}, 10000);
} else {
infoDiv.style.display = "none";
}
});
});
</script>
</body>
</html>