systeme-solaire / index.html
yaspred's picture
Add 1 files
df4cd70 verified
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Système Solaire 3D avec Comète</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.js"></script>
<style>
body {
margin: 0;
overflow: hidden;
background-color: #000;
font-family: Arial, sans-serif;
}
canvas {
display: block;
}
.info-panel {
position: absolute;
bottom: 20px;
left: 20px;
color: white;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 8px;
font-size: 14px;
max-width: 300px;
backdrop-filter: blur(5px);
}
.controls {
position: absolute;
top: 20px;
left: 20px;
color: white;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 8px;
backdrop-filter: blur(5px);
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.planet-label {
position: absolute;
color: white;
font-size: 12px;
pointer-events: none;
text-shadow: 0 0 3px black;
white-space: nowrap;
transform: translate(-50%, -50%);
}
.loading {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #000;
display: flex;
justify-content: center;
align-items: center;
color: white;
font-size: 24px;
z-index: 1000;
}
.speed-control {
width: 150px;
margin: 10px 0;
}
.planet-info {
position: absolute;
right: 20px;
top: 20px;
color: white;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 8px;
max-width: 250px;
backdrop-filter: blur(5px);
display: none;
}
.comet-label {
position: absolute;
color: #aaf;
font-size: 12px;
pointer-events: none;
text-shadow: 0 0 3px black;
white-space: nowrap;
transform: translate(-50%, -50%);
}
</style>
</head>
<body>
<div class="loading" id="loading">
Chargement du système solaire...
</div>
<div class="controls">
<h1 class="text-xl font-bold mb-3 text-yellow-300">Système Solaire 3D</h1>
<div class="mb-3">
<label class="block mb-1">Vitesse de rotation:</label>
<div class="flex items-center">
<input type="range" id="speedControl" min="0" max="5" step="0.1" value="1" class="speed-control mr-3">
<span id="speedValue" class="font-mono">1.0x</span>
</div>
</div>
<div class="flex space-x-2">
<button id="toggleOrbits" class="bg-blue-600 hover:bg-blue-700 text-white py-1 px-3 rounded text-sm transition">
Masquer les orbites
</button>
<button id="toggleLabels" class="bg-purple-600 hover:bg-purple-700 text-white py-1 px-3 rounded text-sm transition">
Masquer les labels
</button>
<button id="toggleComet" class="bg-green-600 hover:bg-green-700 text-white py-1 px-3 rounded text-sm transition">
Masquer la comète
</button>
</div>
</div>
<div class="info-panel">
<div class="flex items-center mb-2">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path>
</svg>
<span>Cliquez sur une planète pour plus d'informations</span>
</div>
<div class="flex items-center">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 15l-2 5L9 9l11 4-5 2zm0 0l5 5M7.188 2.239l.777 2.897M5.136 7.965l-2.898-.777M13.95 4.05l-2.122 2.122m-5.657 5.656l-2.12 2.122"></path>
</svg>
<span>Utilisez la souris pour naviguer</span>
</div>
</div>
<div class="planet-info" id="planetInfo">
<h2 class="text-lg font-bold mb-2" id="planetName">Planète</h2>
<div class="grid grid-cols-2 gap-2 text-sm">
<div>Distance au Soleil:</div>
<div class="font-mono" id="planetDistance">0 UA</div>
<div>Diamètre:</div>
<div class="font-mono" id="planetSize">0 km</div>
<div>Période orbitale:</div>
<div class="font-mono" id="planetPeriod">0 jours</div>
</div>
</div>
<script>
// Vérification que Three.js est chargé
if (!THREE) {
document.getElementById('loading').innerHTML = 'Erreur: Three.js n\'a pas pu être chargé. Veuillez vérifier votre connexion internet.';
throw new Error('Three.js not loaded');
}
// Initialisation de la scène Three.js
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.body.appendChild(renderer.domElement);
// Ajout d'un fond étoilé
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xFFFFFF,
size: 0.1,
transparent: true
});
const starVertices = [];
for (let i = 0; i < 5000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
// Contrôles de la caméra
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.minDistance = 20;
controls.maxDistance = 500;
// Position initiale de la caméra
camera.position.set(0, 50, 150);
controls.update();
// Lumière ambiante
const ambientLight = new THREE.AmbientLight(0x404040);
scene.add(ambientLight);
// Lumière directionnelle (simule le soleil)
const directionalLight = new THREE.DirectionalLight(0xffffff, 1.5);
directionalLight.position.set(0, 0, 0);
scene.add(directionalLight);
// Effet de halo pour le soleil
const sunGlow = new THREE.Mesh(
new THREE.SphereGeometry(6, 32, 32),
new THREE.MeshBasicMaterial({
color: 0xffaa00,
transparent: true,
opacity: 0.3
})
);
scene.add(sunGlow);
// Création du soleil
const sunGeometry = new THREE.SphereGeometry(5, 64, 64);
const sunMaterial = new THREE.MeshBasicMaterial({
color: 0xffff00,
emissive: 0xffff00,
emissiveIntensity: 1
});
const sun = new THREE.Mesh(sunGeometry, sunMaterial);
scene.add(sun);
// Animation du soleil
const sunParticles = new THREE.Group();
for (let i = 0; i < 100; i++) {
const particle = new THREE.Mesh(
new THREE.SphereGeometry(0.1 + Math.random() * 0.3, 8, 8),
new THREE.MeshBasicMaterial({ color: 0xff6600 })
);
// Position aléatoire autour du soleil
const radius = 5 + Math.random() * 3;
const theta = Math.random() * Math.PI * 2;
const phi = Math.random() * Math.PI * 2;
particle.position.x = radius * Math.sin(phi) * Math.cos(theta);
particle.position.y = radius * Math.sin(phi) * Math.sin(theta);
particle.position.z = radius * Math.cos(phi);
sunParticles.add(particle);
}
scene.add(sunParticles);
// Données des planètes (nom, taille, distance, couleur, vitesse, période orbitale)
const planetsData = [
{
name: "Mercure",
size: 0.4,
distance: 15,
color: 0x8B8B8B,
speed: 0.04,
period: 88,
info: "La plus petite planète du système solaire et la plus proche du Soleil."
},
{
name: "Vénus",
size: 0.9,
distance: 20,
color: 0xE6C229,
speed: 0.015,
period: 225,
info: "Similaire à la Terre en taille mais avec une atmosphère toxique de CO₂."
},
{
name: "Terre",
size: 1,
distance: 30,
color: 0x3498db,
speed: 0.01,
period: 365,
info: "Notre planète, la seule connue à abriter la vie."
},
{
name: "Mars",
size: 0.5,
distance: 40,
color: 0xE27B58,
speed: 0.008,
period: 687,
info: "Appelée 'Planète Rouge' à cause de son sol riche en oxyde de fer."
},
{
name: "Jupiter",
size: 2.5,
distance: 60,
color: 0xE3B78D,
speed: 0.002,
period: 4333,
info: "La plus grande planète, une géante gazeuse avec une grande tache rouge."
},
{
name: "Saturne",
size: 2,
distance: 80,
color: 0xF7E39F,
speed: 0.0007,
hasRing: true,
period: 10759,
info: "Connue pour ses magnifiques anneaux composés de glace et de poussière."
},
{
name: "Uranus",
size: 1.5,
distance: 95,
color: 0x7EC0EE,
speed: 0.0005,
period: 30687,
info: "Géante de glace qui tourne sur le côté, avec des anneaux verticaux."
},
{
name: "Neptune",
size: 1.5,
distance: 110,
color: 0x4B70DD,
speed: 0.0003,
period: 60190,
info: "La planète la plus éloignée du Soleil, avec les vents les plus forts."
}
];
const planets = [];
const orbits = [];
const labels = [];
const planetMeshes = [];
// Raycaster pour détecter les clics sur les planètes
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
// Création des planètes et de leurs orbites
planetsData.forEach((data, index) => {
// Planète
const geometry = new THREE.SphereGeometry(data.size, 32, 32);
const material = new THREE.MeshPhongMaterial({
color: data.color,
shininess: 10
});
const planet = new THREE.Mesh(geometry, material);
// Position initiale sur l'orbite
const angle = Math.random() * Math.PI * 2;
planet.position.x = data.distance * Math.cos(angle);
planet.position.z = data.distance * Math.sin(angle);
// Anneaux pour Saturne
if (data.hasRing) {
const ringGeometry = new THREE.RingGeometry(data.size * 1.3, data.size * 1.7, 64);
const ringMaterial = new THREE.MeshPhongMaterial({
color: 0xF7E39F,
side: THREE.DoubleSide,
transparent: true,
opacity: 0.8,
shininess: 30
});
const ring = new THREE.Mesh(ringGeometry, ringMaterial);
ring.rotation.x = Math.PI / 2;
planet.add(ring);
}
scene.add(planet);
planets.push({
mesh: planet,
speed: data.speed,
distance: data.distance,
angle: angle,
data: data
});
planetMeshes.push(planet);
// Orbite
const orbitGeometry = new THREE.RingGeometry(data.distance - 0.1, data.distance + 0.1, 128);
const orbitMaterial = new THREE.MeshBasicMaterial({
color: 0x555555,
side: THREE.DoubleSide,
transparent: true,
opacity: 0.3
});
const orbit = new THREE.Mesh(orbitGeometry, orbitMaterial);
orbit.rotation.x = Math.PI / 2;
scene.add(orbit);
orbits.push(orbit);
// Label
const label = document.createElement('div');
label.className = 'planet-label';
label.textContent = data.name;
label.style.color = `rgb(${Math.floor(data.color >> 16)}, ${Math.floor((data.color >> 8) & 0xff)}, ${Math.floor(data.color & 0xff)})`;
document.body.appendChild(label);
labels.push({ element: label, planet: planet });
});
// Création de la comète
function createComet() {
// Noyau de la comète
const cometGeometry = new THREE.SphereGeometry(0.3, 16, 16);
const cometMaterial = new THREE.MeshPhongMaterial({
color: 0x88ccff,
emissive: 0x88ccff,
emissiveIntensity: 0.5
});
const comet = new THREE.Mesh(cometGeometry, cometMaterial);
// Queue de la comète (particules)
const tailParticles = new THREE.BufferGeometry();
const tailMaterial = new THREE.PointsMaterial({
color: 0x88ffff,
size: 0.1,
transparent: true,
opacity: 0.8,
blending: THREE.AdditiveBlending
});
const tailVertices = [];
for (let i = 0; i < 100; i++) {
// Position aléatoire derrière la comète
const x = -Math.random() * 5;
const y = (Math.random() - 0.5) * 0.5;
const z = (Math.random() - 0.5) * 0.5;
tailVertices.push(x, y, z);
}
tailParticles.setAttribute('position', new THREE.Float32BufferAttribute(tailVertices, 3));
const tail = new THREE.Points(tailParticles, tailMaterial);
comet.add(tail);
// Position initiale aléatoire
const angle = Math.random() * Math.PI * 2;
const distance = 150 + Math.random() * 50;
comet.position.x = Math.cos(angle) * distance;
comet.position.z = Math.sin(angle) * distance;
comet.position.y = (Math.random() - 0.5) * 30;
// Vitesse et direction aléatoires
const velocity = new THREE.Vector3(
(Math.random() - 0.5) * 0.5,
(Math.random() - 0.5) * 0.2,
(Math.random() - 0.5) * 0.5
);
// Label pour la comète
const label = document.createElement('div');
label.className = 'comet-label';
label.textContent = 'Comète';
document.body.appendChild(label);
return {
mesh: comet,
velocity: velocity,
label: label,
tail: tail
};
}
const comet = createComet();
scene.add(comet.mesh);
// Contrôles UI
const speedControl = document.getElementById('speedControl');
const speedValue = document.getElementById('speedValue');
const toggleOrbits = document.getElementById('toggleOrbits');
const toggleLabels = document.getElementById('toggleLabels');
const toggleComet = document.getElementById('toggleComet');
const planetInfo = document.getElementById('planetInfo');
const planetName = document.getElementById('planetName');
const planetDistance = document.getElementById('planetDistance');
const planetSize = document.getElementById('planetSize');
const planetPeriod = document.getElementById('planetPeriod');
let showOrbits = true;
let showLabels = true;
let showComet = true;
let speedFactor = 1;
speedControl.addEventListener('input', (e) => {
speedFactor = parseFloat(e.target.value);
speedValue.textContent = speedFactor.toFixed(1) + 'x';
});
toggleOrbits.addEventListener('click', () => {
showOrbits = !showOrbits;
orbits.forEach(orbit => orbit.visible = showOrbits);
toggleOrbits.textContent = showOrbits ? 'Masquer les orbites' : 'Afficher les orbites';
toggleOrbits.classList.toggle('bg-blue-600');
toggleOrbits.classList.toggle('bg-gray-600');
});
toggleLabels.addEventListener('click', () => {
showLabels = !showLabels;
labels.forEach(label => label.element.style.display = showLabels ? 'block' : 'none');
comet.label.style.display = showLabels ? 'block' : 'none';
toggleLabels.textContent = showLabels ? 'Masquer les labels' : 'Afficher les labels';
toggleLabels.classList.toggle('bg-purple-600');
toggleLabels.classList.toggle('bg-gray-600');
});
toggleComet.addEventListener('click', () => {
showComet = !showComet;
comet.mesh.visible = showComet;
comet.label.style.display = showComet && showLabels ? 'block' : 'none';
toggleComet.textContent = showComet ? 'Masquer la comète' : 'Afficher la comète';
toggleComet.classList.toggle('bg-green-600');
toggleComet.classList.toggle('bg-gray-600');
});
// Gestion des clics sur les planètes
window.addEventListener('click', (event) => {
// Calcul de la position de la souris en coordonnées normalisées
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
// Mise à jour du raycaster
raycaster.setFromCamera(mouse, camera);
// Calcul des objets intersectés
const intersects = raycaster.intersectObjects(planetMeshes);
if (intersects.length > 0) {
const planetMesh = intersects[0].object;
const planetData = planets.find(p => p.mesh === planetMesh).data;
// Affichage des informations de la planète
planetName.textContent = planetData.name;
planetDistance.textContent = planetData.distance + " UA";
planetSize.textContent = (planetData.size * 12742).toFixed(0) + " km";
planetPeriod.textContent = planetData.period + " jours terrestres";
// Animation du panneau d'information
planetInfo.style.display = 'block';
planetInfo.style.opacity = '0';
planetInfo.style.transform = 'translateX(20px)';
setTimeout(() => {
planetInfo.style.opacity = '1';
planetInfo.style.transform = 'translateX(0)';
}, 10);
}
});
// Animation
function animate() {
requestAnimationFrame(animate);
// Rotation des planètes autour du soleil
planets.forEach(planet => {
planet.angle += planet.speed * speedFactor;
planet.mesh.position.x = Math.cos(planet.angle) * planet.distance;
planet.mesh.position.z = Math.sin(planet.angle) * planet.distance;
// Rotation sur elles-mêmes
planet.mesh.rotation.y += 0.01 * speedFactor;
});
// Mise à jour des labels
labels.forEach(label => {
const screenPosition = label.planet.position.clone().project(camera);
const x = (screenPosition.x * 0.5 + 0.5) * window.innerWidth;
const y = (-(screenPosition.y * 0.5 + 0.5) + 1) * window.innerHeight;
label.element.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
});
// Mise à jour du label de la comète
const cometScreenPos = comet.mesh.position.clone().project(camera);
const cometX = (cometScreenPos.x * 0.5 + 0.5) * window.innerWidth;
const cometY = (-(cometScreenPos.y * 0.5 + 0.5) + 1) * window.innerHeight;
comet.label.style.transform = `translate(-50%, -50%) translate(${cometX}px,${cometY}px)`;
// Animation du soleil
sun.rotation.y += 0.002 * speedFactor;
sunGlow.scale.set(1 + Math.sin(Date.now() * 0.001) * 0.05, 1, 1);
// Animation des particules solaires
sunParticles.rotation.y += 0.001 * speedFactor;
sunParticles.children.forEach((particle, i) => {
particle.position.x += (Math.random() - 0.5) * 0.1;
particle.position.y += (Math.random() - 0.5) * 0.1;
particle.position.z += (Math.random() - 0.5) * 0.1;
// Ramener les particules vers le soleil si elles s'éloignent trop
const distance = particle.position.length();
if (distance > 8) {
particle.position.normalize().multiplyScalar(5 + Math.random() * 2);
}
});
// Animation de la comète
comet.mesh.position.x += comet.velocity.x * speedFactor;
comet.mesh.position.y += comet.velocity.y * speedFactor;
comet.mesh.position.z += comet.velocity.z * speedFactor;
// Faire tourner la queue de la comète
comet.tail.rotation.y += 0.01 * speedFactor;
// Si la comète sort de la scène, la repositionner de l'autre côté
if (Math.abs(comet.mesh.position.x) > 200 ||
Math.abs(comet.mesh.position.y) > 100 ||
Math.abs(comet.mesh.position.z) > 200) {
// Nouvelle position aléatoire
const angle = Math.random() * Math.PI * 2;
const distance = 150 + Math.random() * 50;
comet.mesh.position.x = Math.cos(angle) * distance;
comet.mesh.position.z = Math.sin(angle) * distance;
comet.mesh.position.y = (Math.random() - 0.5) * 30;
// Nouvelle direction
comet.velocity.set(
(Math.random() - 0.5) * 0.5,
(Math.random() - 0.5) * 0.2,
(Math.random() - 0.5) * 0.5
);
}
// Orientation de la comète vers sa direction de mouvement
comet.mesh.lookAt(
comet.mesh.position.x + comet.velocity.x,
comet.mesh.position.y + comet.velocity.y,
comet.mesh.position.z + comet.velocity.z
);
controls.update();
renderer.render(scene, camera);
}
// Redimensionnement
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
// Cacher l'écran de chargement une fois que tout est prêt
window.addEventListener('load', () => {
setTimeout(() => {
document.getElementById('loading').style.opacity = '0';
setTimeout(() => {
document.getElementById('loading').style.display = 'none';
}, 500);
}, 1000);
});
animate();
</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=yaspred/systeme-solaire" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>