Fix: Corriger les chemins relatifs pour GitHub Pages
This commit is contained in:
Binary file not shown.
@@ -1,332 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Sirius en Guadeloupe : Guide du Lever Héliaque</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&family=Playfair+Display:wght@700&display=swap" rel="stylesheet">
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
|
||||
<!-- Chosen Palette: Celestial Harmony (Deep Navy, Gold, Cream/Light Gray) -->
|
||||
<!-- Application Structure Plan: A user-centric, single-page application featuring a prominent interactive prediction tool as the main element. Users select a location and year to get an immediate result. Below this tool, a tab-based navigation allows non-linear exploration of other key content from the report: 1) "Prédictions" (the tool and full data table), 2) "Comprendre" (celestial mechanics explained in digestible cards), 3) "Observer" (a practical guide with a Stellarium tutorial and tips), and 4) "Histoires" (the cultural significance of Sirius). This structure prioritizes the user's primary task (finding a date) while making the rich contextual information easily accessible and not overwhelming. -->
|
||||
<!-- Visualization & Content Choices: The primary interactive element is a "Prediction Calculator" (HTML selects + JS), not a chart, as the core data is a lookup table. Goal: Inform/Interact. Method: Dropdowns update a dynamic result card. Justification: Most direct way to answer the user's key question. The full data is presented in a standard HTML table for comparison. Goal: Compare. Method: Table. Justification: Standard and effective. Explanatory content (mechanics, culture) is organized into themed cards and sections toggled by JS. Goal: Organize/Inform. Method: HTML/CSS cards. Justification: Prevents walls of text, improves readability. Icons are Unicode characters. -->
|
||||
<!-- CONFIRMATION: NO SVG graphics used. NO Mermaid JS used. -->
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Inter', sans-serif;
|
||||
background-color: #f3f4f6; /* bg-gray-100 */
|
||||
}
|
||||
h1, h2, h3 {
|
||||
font-family: 'Playfair Display', serif;
|
||||
}
|
||||
.tab-button.active {
|
||||
border-color: #fbbf24; /* border-amber-400 */
|
||||
color: #1e3a8a; /* text-blue-900 */
|
||||
font-weight: 600;
|
||||
}
|
||||
.celestial-card {
|
||||
background-color: #ffffff;
|
||||
border-radius: 0.75rem;
|
||||
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
.celestial-header {
|
||||
background-color: #1e3a8a; /* bg-blue-900 */
|
||||
color: #ffffff;
|
||||
}
|
||||
.highlight-text {
|
||||
color: #fbbf24; /* text-amber-400 */
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="text-gray-800">
|
||||
|
||||
<header class="celestial-header text-center p-6 sm:p-8 shadow-lg">
|
||||
<h1 class="text-3xl sm:text-4xl md:text-5xl font-bold tracking-tight">Sirius en Guadeloupe</h1>
|
||||
<p class="text-lg sm:text-xl text-gray-200 mt-2">Votre guide interactif du lever héliaque</p>
|
||||
</header>
|
||||
|
||||
<main class="max-w-5xl mx-auto p-4 sm:p-6 lg:p-8">
|
||||
|
||||
<div id="interactive-predictor" class="celestial-card p-6 md:p-8 mb-8">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-center mb-2 text-blue-900">Quand observer Sirius ?</h2>
|
||||
<p class="text-center text-gray-600 mb-6">Sélectionnez un site et une année pour trouver la date et l'heure du premier lever visible de Sirius à l'aube.</p>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
|
||||
<div>
|
||||
<label for="location-select" class="block text-sm font-medium text-gray-700 mb-1">Choisissez un site d'observation :</label>
|
||||
<select id="location-select" class="w-full p-3 border border-gray-300 rounded-md shadow-sm focus:ring-amber-400 focus:border-amber-400">
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label for="year-select" class="block text-sm font-medium text-gray-700 mb-1">Choisissez une année :</label>
|
||||
<select id="year-select" class="w-full p-3 border border-gray-300 rounded-md shadow-sm focus:ring-amber-400 focus:border-amber-400">
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="result-display" class="bg-blue-900 text-white rounded-lg p-6 text-center transition-all duration-500 transform scale-100">
|
||||
<h3 id="result-location" class="text-2xl font-bold">Pointe des Châteaux</h3>
|
||||
<p class="text-5xl font-bold my-3 highlight-text" id="result-date">22 juillet</p>
|
||||
<p class="text-3xl" id="result-time">vers 05:12</p>
|
||||
<div class="mt-4 pt-4 border-t border-blue-700">
|
||||
<p class="text-sm text-blue-200">Fenêtre d'observation recommandée :</p>
|
||||
<p class="font-semibold text-lg" id="result-window">20 au 24 Juillet</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="w-full">
|
||||
<div class="border-b border-gray-300 mb-6">
|
||||
<nav class="-mb-px flex flex-wrap justify-center gap-x-4 gap-y-2 sm:gap-x-6" aria-label="Tabs">
|
||||
<button data-tab="predictions" class="tab-button active whitespace-nowrap py-3 px-1 border-b-2 font-medium text-base text-gray-500 border-transparent hover:border-gray-400">
|
||||
Prédictions
|
||||
</button>
|
||||
<button data-tab="understand" class="tab-button whitespace-nowrap py-3 px-1 border-b-2 font-medium text-base text-gray-500 border-transparent hover:border-gray-400">
|
||||
Comprendre
|
||||
</button>
|
||||
<button data-tab="observe" class="tab-button whitespace-nowrap py-3 px-1 border-b-2 font-medium text-base text-gray-500 border-transparent hover:border-gray-400">
|
||||
Observer
|
||||
</button>
|
||||
<button data-tab="stories" class="tab-button whitespace-nowrap py-3 px-1 border-b-2 font-medium text-base text-gray-500 border-transparent hover:border-gray-400">
|
||||
Histoires
|
||||
</button>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<div id="tab-content">
|
||||
<div id="predictions-content" class="tab-pane">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-blue-900 mb-4">Tableau des Prédictions</h2>
|
||||
<p class="mb-6 text-gray-600">Retrouvez ici l'ensemble des dates et heures estimées du lever héliaque de Sirius pour tous les sites en Guadeloupe, de 2025 à 2029. Ces données sont des estimations pour des conditions idéales et constituent la meilleure base pour planifier vos observations.</p>
|
||||
<div class="overflow-x-auto celestial-card p-4">
|
||||
<table class="min-w-full divide-y divide-gray-200">
|
||||
<thead class="bg-gray-50">
|
||||
<tr>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Lieu d'Observation</th>
|
||||
<th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider">2025</th>
|
||||
<th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider">2026</th>
|
||||
<th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider">2027</th>
|
||||
<th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider">2028</th>
|
||||
<th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider">2029</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="predictions-table-body" class="bg-white divide-y divide-gray-200">
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="understand-content" class="tab-pane hidden">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-blue-900 mb-4">Comprendre le Phénomène</h2>
|
||||
<p class="mb-6 text-gray-600">Le lever héliaque n'est pas qu'un simple lever d'étoile. C'est un événement astronomique précis, fruit d'une danse cosmique entre la Terre, le Soleil et Sirius. Cette section vous donne les clés pour comprendre la science qui se cache derrière la poésie de ce "premier regard" annuel.</p>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<div class="celestial-card p-6">
|
||||
<h3 class="font-bold text-xl mb-2 text-blue-900">Définition</h3>
|
||||
<p class="text-gray-600">Le lever héliaque est la première réapparition d'une étoile à l'aube après sa période d'invisibilité due à la proximité du Soleil. C'est un marqueur de temps naturel utilisé par de nombreuses civilisations anciennes.</p>
|
||||
</div>
|
||||
<div class="celestial-card p-6">
|
||||
<h3 class="font-bold text-xl mb-2 text-blue-900">Arcus Visionis</h3>
|
||||
<p class="text-gray-600">C'est l'angle clé ! Il s'agit de la hauteur négative du Soleil sous l'horizon, nécessaire pour que l'étoile devienne tout juste visible dans le ciel de l'aube. Pour la brillante Sirius, cet angle est d'environ 9° à 10°.</p>
|
||||
</div>
|
||||
<div class="celestial-card p-6">
|
||||
<h3 class="font-bold text-xl mb-2 text-blue-900">Facteurs d'Influence</h3>
|
||||
<p class="text-gray-600">La date exacte dépend de la brillance de l'étoile, de la latitude du lieu (qui change la géométrie du lever), et surtout de l'extinction atmosphérique (humidité, brume de sable) qui peut affaiblir la lumière de l'étoile.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="observe-content" class="tab-pane hidden">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-blue-900 mb-4">Guide Pratique d'Observation</h2>
|
||||
<p class="mb-6 text-gray-600">Passer de la théorie à la pratique demande un peu de préparation. Cette section vous guide pour mettre toutes les chances de votre côté : choisir le bon équipement (le plus simple qui soit), utiliser un outil de simulation comme Stellarium et, surtout, comprendre les marges d'erreur pour ne pas manquer le spectacle.</p>
|
||||
<div class="space-y-6">
|
||||
<div class="celestial-card p-6">
|
||||
<h3 class="font-bold text-xl mb-2 text-blue-900">Votre Équipement</h3>
|
||||
<ul class="list-disc list-inside space-y-2 text-gray-600">
|
||||
<li><span class="font-semibold">Vos yeux :</span> Le plus important ! Arrivez 20 minutes en avance pour les habituer à l'obscurité.</li>
|
||||
<li><span class="font-semibold">Des jumelles (optionnel) :</span> Elles peuvent aider à repérer l'étoile dans les lueurs de l'aube.</li>
|
||||
<li><span class="font-semibold">Une boussole ou une app smartphone :</span> Pour être certain de regarder vers l'Est-Sud-Est.</li>
|
||||
<li><span class="font-semibold">Patience et vêtements chauds :</span> Les nuits peuvent être fraîches, même en juillet.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="celestial-card p-6">
|
||||
<h3 class="font-bold text-xl mb-2 text-blue-900">Utiliser Stellarium (Logiciel Gratuit)</h3>
|
||||
<ol class="list-decimal list-inside space-y-2 text-gray-600">
|
||||
<li><span class="font-semibold">Configurez votre lieu (F6) :</span> Entrez la latitude et longitude du site choisi.</li>
|
||||
<li><span class="font-semibold">Réglez la date (F5) :</span> Choisissez une date autour de celle prédite (ex: 22 juillet 2025) et une heure vers 5h00.</li>
|
||||
<li><span class="font-semibold">Cherchez "Sirius" (F3) :</span> Le logiciel pointera vers l'étoile.</li>
|
||||
<li><span class="font-semibold">Simulez :</span> Avancez le temps minute par minute pour voir Sirius se lever à l'Est avant que le ciel ne devienne trop clair.</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div class="celestial-card p-6 bg-amber-50 border border-amber-300">
|
||||
<h3 class="font-bold text-xl mb-2 text-amber-800">Conseil Crucial : La Fenêtre d'Observation</h3>
|
||||
<p class="text-amber-700">Les dates calculées sont pour un ciel parfait. La météo (nuages, brume) peut retarder la visibilité. <strong class="font-semibold">Commencez vos observations 2 jours AVANT la date prédite et continuez 2 à 3 jours APRÈS.</strong> Cette fenêtre de 4-5 jours maximise vos chances de succès !</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="stories-content" class="tab-pane hidden">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-blue-900 mb-4">Sirius, Miroir des Cultures</h2>
|
||||
<p class="mb-6 text-gray-600">Observer Sirius, c'est se connecter à une histoire millénaire. Pour de nombreuses cultures, en particulier africaines, son lever héliaque n'était pas un simple fait astronomique mais un événement spirituel et culturel majeur, annonciateur de renouveau et de vie. Découvrez ici quelques-unes de ces histoires fascinantes.</p>
|
||||
<div class="space-y-6">
|
||||
<div class="celestial-card p-6">
|
||||
<h3 class="font-bold text-xl mb-2 text-blue-900">Égypte Antique : Sothis, l'Annonciatrice de Vie</h3>
|
||||
<p class="text-gray-600">Pour les Égyptiens, le lever héliaque de Sirius (nommée Sothis) était l'événement le plus important de l'année. Il annonçait la crue du Nil, qui fertilisait les terres et assurait la survie du royaume. Ce phénomène marquait le Nouvel An et était associé à la déesse Isis, symbole de renaissance. C'était le véritable début du cycle de la vie.</p>
|
||||
</div>
|
||||
<div class="celestial-card p-6">
|
||||
<h3 class="font-bold text-xl mb-2 text-blue-900">L'Énigme des Dogon du Mali</h3>
|
||||
<p class="text-gray-600">Le peuple Dogon possède un savoir astronomique sur Sirius qui stupéfie les chercheurs. Leur tradition orale décrit Sirius comme un système double, avec une compagne invisible, très petite et très lourde (Sirius B), tournant autour de l'étoile principale en 50 ans. Des connaissances qui correspondent précisément aux découvertes modernes, et dont l'origine reste un fascinant mystère scientifique et culturel.</p>
|
||||
</div>
|
||||
<div class="celestial-card p-6">
|
||||
<h3 class="font-bold text-xl mb-2 text-blue-900">Échos Stellaires Mondiaux</h3>
|
||||
<p class="text-gray-600">Sirius a captivé le monde entier. Les Grecs l'appelaient "l'ardente" et son lever annonçait les chaleurs de la "canicule". Pour les navigateurs polynésiens, c'était une étoile guide essentielle pour leurs voyages dans le Pacifique. Elle est même mentionnée dans le Coran sous le nom d'al-Shi'ra. Observer Sirius, c'est partager un regard avec toute l'humanité.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
|
||||
<footer class="text-center py-6 mt-8 text-gray-500 text-sm">
|
||||
<p>Application créée à partir du rapport "Sirius en Guadeloupe : Guide Astronomique et Culturel".</p>
|
||||
<p>© 2025 - Levez les yeux vers le ciel.</p>
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
const predictionsData = {
|
||||
"Pointe des Châteaux": {"2025": "22 juillet, 05:12", "2026": "22 juillet, 05:12", "2027": "22 juillet, 05:13", "2028": "21 juillet, 05:13", "2029": "22 juillet, 05:14"},
|
||||
"Pointe de la Grande Vigie": {"2025": "22 juillet, 05:11", "2026": "22 juillet, 05:12", "2027": "22 juillet, 05:12", "2028": "21 juillet, 05:12", "2029": "22 juillet, 05:13"},
|
||||
"Duzer (Sainte-Rose)": {"2025": "22 juillet, 05:13", "2026": "22 juillet, 05:14", "2027": "22 juillet, 05:14", "2028": "21 juillet, 05:14", "2029": "22 juillet, 05:15"},
|
||||
"Pointe du Vieux-Fort": {"2025": "22 juillet, 05:14", "2026": "22 juillet, 05:14", "2027": "22 juillet, 05:15", "2028": "21 juillet, 05:15", "2029": "22 juillet, 05:16"},
|
||||
"Grande Pointe (Trois-Rivières)": {"2025": "22 juillet, 05:13", "2026": "22 juillet, 05:14", "2027": "22 juillet, 05:14", "2028": "21 juillet, 05:15", "2029": "22 juillet, 05:15"},
|
||||
"Petit-Pérou": {"2025": "22 juillet, 05:14", "2026": "22 juillet, 05:14", "2027": "22 juillet, 05:15", "2028": "21 juillet, 05:15", "2029": "22 juillet, 05:16"},
|
||||
"Saint-Félix (Le Gosier)": {"2025": "22 juillet, 05:13", "2026": "22 juillet, 05:13", "2027": "22 juillet, 05:14", "2028": "21 juillet, 05:14", "2029": "22 juillet, 05:15"}
|
||||
};
|
||||
|
||||
const locations = Object.keys(predictionsData);
|
||||
const years = ["2025", "2026", "2027", "2028", "2029"];
|
||||
|
||||
const locationSelect = document.getElementById('location-select');
|
||||
const yearSelect = document.getElementById('year-select');
|
||||
const resultLocation = document.getElementById('result-location');
|
||||
const resultDate = document.getElementById('result-date');
|
||||
const resultTime = document.getElementById('result-time');
|
||||
const resultWindow = document.getElementById('result-window');
|
||||
const predictionsTableBody = document.getElementById('predictions-table-body');
|
||||
const tabs = document.querySelectorAll('.tab-button');
|
||||
const tabPanes = document.querySelectorAll('.tab-pane');
|
||||
|
||||
function populateSelectors() {
|
||||
locations.forEach(location => {
|
||||
const option = document.createElement('option');
|
||||
option.value = location;
|
||||
option.textContent = location;
|
||||
locationSelect.appendChild(option);
|
||||
});
|
||||
years.forEach(year => {
|
||||
const option = document.createElement('option');
|
||||
option.value = year;
|
||||
option.textContent = year;
|
||||
yearSelect.appendChild(option);
|
||||
});
|
||||
}
|
||||
|
||||
function updateDisplay() {
|
||||
const selectedLocation = locationSelect.value;
|
||||
const selectedYear = yearSelect.value;
|
||||
const prediction = predictionsData[selectedLocation][selectedYear];
|
||||
|
||||
const [datePart, timePart] = prediction.split(', ');
|
||||
|
||||
resultLocation.textContent = selectedLocation;
|
||||
resultDate.textContent = datePart;
|
||||
resultTime.textContent = `vers ${timePart}`;
|
||||
|
||||
const day = parseInt(datePart.split(' ')[0]);
|
||||
const month = datePart.split(' ')[1];
|
||||
const windowStart = day - 2;
|
||||
const windowEnd = day + 2;
|
||||
resultWindow.textContent = `${windowStart} au ${windowEnd} ${month}`;
|
||||
|
||||
document.getElementById('result-display').classList.remove('scale-95');
|
||||
document.getElementById('result-display').classList.add('scale-100');
|
||||
|
||||
updateTableHighlight(selectedLocation);
|
||||
}
|
||||
|
||||
function populateTable() {
|
||||
locations.forEach(location => {
|
||||
const row = document.createElement('tr');
|
||||
row.id = `row-${location.replace(/[^a-zA-Z0-9]/g, '-')}`;
|
||||
row.className = 'transition-colors duration-300';
|
||||
|
||||
const locationCell = document.createElement('td');
|
||||
locationCell.className = "px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900";
|
||||
locationCell.textContent = location;
|
||||
row.appendChild(locationCell);
|
||||
|
||||
years.forEach(year => {
|
||||
const cell = document.createElement('td');
|
||||
cell.className = "px-6 py-4 whitespace-nowrap text-sm text-gray-500 text-center";
|
||||
const [datePart, timePart] = predictionsData[location][year].split(', ');
|
||||
cell.innerHTML = `${datePart}<br><span class="text-xs">${timePart}</span>`;
|
||||
row.appendChild(cell);
|
||||
});
|
||||
|
||||
predictionsTableBody.appendChild(row);
|
||||
});
|
||||
}
|
||||
|
||||
function updateTableHighlight(selectedLocation) {
|
||||
document.querySelectorAll('#predictions-table-body tr').forEach(row => {
|
||||
row.classList.remove('bg-amber-100');
|
||||
});
|
||||
const rowId = `row-${selectedLocation.replace(/[^a-zA-Z0-9]/g, '-')}`;
|
||||
const activeRow = document.getElementById(rowId);
|
||||
if (activeRow) {
|
||||
activeRow.classList.add('bg-amber-100');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function handleTabClick(event) {
|
||||
tabs.forEach(tab => {
|
||||
tab.classList.remove('active');
|
||||
});
|
||||
event.currentTarget.classList.add('active');
|
||||
|
||||
tabPanes.forEach(pane => {
|
||||
pane.classList.add('hidden');
|
||||
});
|
||||
|
||||
const tabId = event.currentTarget.dataset.tab;
|
||||
document.getElementById(`${tabId}-content`).classList.remove('hidden');
|
||||
}
|
||||
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
populateSelectors();
|
||||
populateTable();
|
||||
updateDisplay();
|
||||
|
||||
locationSelect.addEventListener('change', () => {
|
||||
document.getElementById('result-display').classList.add('scale-95');
|
||||
setTimeout(updateDisplay, 200);
|
||||
});
|
||||
yearSelect.addEventListener('change', () => {
|
||||
document.getElementById('result-display').classList.add('scale-95');
|
||||
setTimeout(updateDisplay, 200);
|
||||
});
|
||||
|
||||
tabs.forEach(tab => {
|
||||
tab.addEventListener('click', handleTabClick);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
+2
-2
@@ -2,7 +2,7 @@
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<link rel="icon" type="image/svg+xml" href="./vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Sirius en Guadeloupe - Guide du Lever Héliaque</title>
|
||||
<!-- Google Fonts -->
|
||||
@@ -12,6 +12,6 @@
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
<script type="module" src="./src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,263 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Infographie 3D : La Vague Planétaire de Sirius</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&family=Playfair+Display:wght@700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Inter', sans-serif;
|
||||
background-color: #0a192f;
|
||||
color: #ccd6f6;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
h1, h2, h3 {
|
||||
font-family: 'Playfair Display', serif;
|
||||
color: #ffffff;
|
||||
}
|
||||
#globe-container {
|
||||
cursor: grab;
|
||||
width: 100%;
|
||||
max-width: 800px;
|
||||
margin: auto;
|
||||
aspect-ratio: 1 / 1;
|
||||
}
|
||||
#tooltip {
|
||||
position: absolute;
|
||||
display: none;
|
||||
background-color: rgba(10, 25, 47, 0.85);
|
||||
color: #ccd6f6;
|
||||
padding: 8px 12px;
|
||||
border-radius: 6px;
|
||||
font-size: 0.9rem;
|
||||
pointer-events: none;
|
||||
border: 1px solid #303C55;
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="antialiased">
|
||||
|
||||
<div class="max-w-5xl mx-auto p-4 md:p-8">
|
||||
|
||||
<header class="text-center my-12">
|
||||
<h1 class="text-3xl md:text-5xl font-bold tracking-tight">La Vague Planétaire de Sirius</h1>
|
||||
<p class="text-lg md:text-xl mt-4 text-gray-400">Une animation 3D du lever héliaque autour du globe</p>
|
||||
</header>
|
||||
|
||||
<section class="my-8">
|
||||
<p class="text-center max-w-3xl mx-auto mb-8">
|
||||
Interagissez avec le globe pour explorer la progression du lever héliaque de Sirius. L'onde lumineuse animée représente la "vague de visibilité" qui se déplace de l'hémisphère Sud (fin juin) vers le Nord (fin juillet). Survolez les points pour voir les détails de chaque lieu. Vous pouvez faire tourner le globe en cliquant et en déplaçant la souris.
|
||||
</p>
|
||||
|
||||
<div id="globe-container" class="shadow-2xl rounded-full"></div>
|
||||
<div id="tooltip"></div>
|
||||
|
||||
</section>
|
||||
|
||||
<section class="my-16">
|
||||
<h2 class="text-2xl md:text-3xl font-bold text-center mb-6">Le Moteur du Phénomène : Latitude et Saisons</h2>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-8 max-w-4xl mx-auto">
|
||||
<div class="bg-[#112240] p-6 rounded-lg border border-gray-700">
|
||||
<h3 class="font-bold text-xl mb-2">Départ au Sud</h3>
|
||||
<p class="text-gray-400">La vague commence dans l'hémisphère Sud car c'est l'hiver austral. Les nuits étant plus longues, le ciel reste sombre plus longtemps à l'aube, permettant à Sirius de se montrer plus tôt dans l'année (fin juin).</p>
|
||||
</div>
|
||||
<div class="bg-[#112240] p-6 rounded-lg border border-gray-700">
|
||||
<h3 class="font-bold text-xl mb-2">Arrivée au Nord</h3>
|
||||
<p class="text-gray-400">La vague atteint l'hémisphère Nord en plein été boréal. Les nuits sont plus courtes, il faut donc attendre plus longtemps (fin juillet) pour que le Soleil soit suffisamment loin sous l'horizon pour laisser Sirius apparaître.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer class="text-center text-gray-500 text-sm mt-16 py-8 border-t border-gray-700">
|
||||
<p>Animation 3D réalisée avec Three.js. Données basées sur le rapport des éphémérides.</p>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let scene, camera, renderer, globe, raycaster, mouse;
|
||||
let INTERSECTED;
|
||||
const cities = [
|
||||
{ name: 'La Réunion', lat: -20.88, lon: 55.45, date: '27 Juin' },
|
||||
{ name: 'Kinshasa', lat: -4.44, lon: 15.26, date: '16 Juillet' },
|
||||
{ name: 'Guadeloupe', lat: 16.26, lon: -61.55, date: '22 Juillet' },
|
||||
{ name: 'Martinique', lat: 14.64, lon: -61.02, date: '23 Juillet' },
|
||||
{ name: 'Dakar', lat: 14.71, lon: -17.46, date: '23 Juillet' },
|
||||
{ name: 'Addis-Abeba', lat: 9.03, lon: 38.74, date: '26 Juillet' },
|
||||
{ name: 'Abidjan', lat: 5.36, lon: -4.00, date: '28 Juillet' },
|
||||
{ name: 'Lomé', lat: 6.13, lon: 1.21, date: '28 Juillet' },
|
||||
{ name: 'Accra', lat: 5.60, lon: -0.18, date: '28 Juillet' },
|
||||
{ name: 'Benin City', lat: 6.33, lon: 5.62, date: '28 Juillet' },
|
||||
{ name: 'Juba', lat: 4.85, lon: 31.57, date: '28 Juillet' }
|
||||
];
|
||||
const cityMarkers = new THREE.Group();
|
||||
const tooltip = document.getElementById('tooltip');
|
||||
let wave;
|
||||
|
||||
function init() {
|
||||
const container = document.getElementById('globe-container');
|
||||
|
||||
// Scene
|
||||
scene = new THREE.Scene();
|
||||
|
||||
// Camera
|
||||
camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 1000);
|
||||
camera.position.z = 3.5;
|
||||
|
||||
// Renderer
|
||||
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
|
||||
renderer.setSize(container.clientWidth, container.clientHeight);
|
||||
renderer.setPixelRatio(window.devicePixelRatio);
|
||||
container.appendChild(renderer.domElement);
|
||||
|
||||
// Lights
|
||||
scene.add(new THREE.AmbientLight(0xcccccc, 0.5));
|
||||
const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);
|
||||
dirLight.position.set(5, 3, 5);
|
||||
scene.add(dirLight);
|
||||
|
||||
// Globe
|
||||
const loader = new THREE.TextureLoader();
|
||||
const texture = loader.load('https://raw.githubusercontent.com/jeromeetienne/threex.planets/master/images/earthmap1k.jpg', () => {
|
||||
const globeGeometry = new THREE.SphereGeometry(1, 64, 64);
|
||||
const globeMaterial = new THREE.MeshPhongMaterial({ map: texture, color: 0x99aaff });
|
||||
globe = new THREE.Mesh(globeGeometry, globeMaterial);
|
||||
scene.add(globe);
|
||||
globe.add(cityMarkers);
|
||||
plotCities();
|
||||
});
|
||||
|
||||
// Animated Wave
|
||||
const waveGeometry = new THREE.TorusGeometry(1.01, 0.05, 16, 100);
|
||||
waveGeometry.rotateX(Math.PI / 2);
|
||||
const waveMaterial = new THREE.MeshBasicMaterial({
|
||||
color: 0x64ffda,
|
||||
transparent: true,
|
||||
opacity: 0.4,
|
||||
side: THREE.DoubleSide
|
||||
});
|
||||
wave = new THREE.Mesh(waveGeometry, waveMaterial);
|
||||
scene.add(wave);
|
||||
|
||||
// Raycaster
|
||||
raycaster = new THREE.Raycaster();
|
||||
mouse = new THREE.Vector2();
|
||||
|
||||
// Event Listeners
|
||||
container.addEventListener('mousemove', onMouseMove, false);
|
||||
container.addEventListener('mousedown', onMouseDown, false);
|
||||
window.addEventListener('resize', onWindowResize, false);
|
||||
}
|
||||
|
||||
function plotCities() {
|
||||
cities.forEach(city => {
|
||||
const latRad = city.lat * (Math.PI / 180);
|
||||
const lonRad = -city.lon * (Math.PI / 180);
|
||||
const x = Math.cos(latRad) * Math.cos(lonRad);
|
||||
const y = Math.sin(latRad);
|
||||
const z = Math.cos(latRad) * Math.sin(lonRad);
|
||||
|
||||
const markerGeometry = new THREE.SphereGeometry(0.015, 16, 16);
|
||||
const markerMaterial = new THREE.MeshBasicMaterial({ color: 0x64ffda });
|
||||
const marker = new THREE.Mesh(markerGeometry, markerMaterial);
|
||||
marker.position.set(x, y, z);
|
||||
marker.userData = { name: city.name, date: city.date };
|
||||
cityMarkers.add(marker);
|
||||
});
|
||||
}
|
||||
|
||||
let isDragging = false;
|
||||
let previousMousePosition = { x: 0, y: 0 };
|
||||
|
||||
function onMouseDown(event) {
|
||||
isDragging = true;
|
||||
}
|
||||
|
||||
function onMouseMove(event) {
|
||||
const container = document.getElementById('globe-container');
|
||||
const rect = container.getBoundingClientRect();
|
||||
|
||||
// For dragging
|
||||
if (isDragging) {
|
||||
const deltaMove = {
|
||||
x: event.clientX - previousMousePosition.x,
|
||||
y: event.clientY - previousMousePosition.y
|
||||
};
|
||||
|
||||
const rotateAngleX = (deltaMove.y * 0.5) * (Math.PI / 180);
|
||||
const rotateAngleY = (deltaMove.x * 0.5) * (Math.PI / 180);
|
||||
|
||||
globe.rotation.x += rotateAngleX;
|
||||
globe.rotation.y += rotateAngleY;
|
||||
}
|
||||
|
||||
previousMousePosition = { x: event.clientX, y: event.clientY };
|
||||
|
||||
// For raycasting
|
||||
mouse.x = ((event.clientX - rect.left) / container.clientWidth) * 2 - 1;
|
||||
mouse.y = -((event.clientY - rect.top) / container.clientHeight) * 2 + 1;
|
||||
|
||||
// For tooltip
|
||||
tooltip.style.left = `${event.clientX + 15}px`;
|
||||
tooltip.style.top = `${event.clientY + 15}px`;
|
||||
}
|
||||
|
||||
document.addEventListener('mouseup', () => { isDragging = false; });
|
||||
|
||||
function onWindowResize() {
|
||||
const container = document.getElementById('globe-container');
|
||||
camera.aspect = container.clientWidth / container.clientHeight;
|
||||
camera.updateProjectionMatrix();
|
||||
renderer.setSize(container.clientWidth, container.clientHeight);
|
||||
}
|
||||
|
||||
function animate() {
|
||||
requestAnimationFrame(animate);
|
||||
|
||||
if (!isDragging) {
|
||||
globe.rotation.y += 0.001;
|
||||
}
|
||||
|
||||
// Animate the wave
|
||||
const time = Date.now() * 0.0002;
|
||||
// A sine wave moving from south pole (-PI/2) to north pole (PI/2)
|
||||
const latAngle = Math.sin(time) * (Math.PI / 2);
|
||||
wave.position.y = Math.sin(latAngle);
|
||||
const scale = Math.cos(latAngle);
|
||||
wave.scale.set(scale, 1, scale);
|
||||
|
||||
// Raycasting logic
|
||||
raycaster.setFromCamera(mouse, camera);
|
||||
const intersects = raycaster.intersectObjects(cityMarkers.children);
|
||||
|
||||
if (intersects.length > 0) {
|
||||
if (INTERSECTED != intersects[0].object) {
|
||||
if (INTERSECTED) INTERSECTED.material.emissive.setHex(INTERSECTED.currentHex);
|
||||
INTERSECTED = intersects[0].object;
|
||||
INTERSECTED.currentHex = INTERSECTED.material.emissive.getHex();
|
||||
INTERSECTED.material.emissive.setHex(0xff0000);
|
||||
|
||||
tooltip.style.display = 'block';
|
||||
tooltip.innerHTML = `<strong>${INTERSECTED.userData.name}</strong><br>${INTERSECTED.userData.date}`;
|
||||
}
|
||||
} else {
|
||||
if (INTERSECTED) INTERSECTED.material.emissive.setHex(INTERSECTED.currentHex);
|
||||
INTERSECTED = null;
|
||||
tooltip.style.display = 'none';
|
||||
}
|
||||
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
|
||||
init();
|
||||
animate();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,317 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Infographie : Le Lever Héliaque de Sirius en Guadeloupe</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700;900&family=Playfair+Display:wght@700&display=swap" rel="stylesheet">
|
||||
<!-- Chosen Palette: Brilliant Blues -->
|
||||
<!-- Application Structure Plan: The infographic follows a narrative scroll format. 1. Hook: Large title and key stats (Magnitude, Invisibility Period). 2. Science: Simplified explanation of the celestial mechanics with a custom HTML/CSS diagram for Arcus Visionis and cards for influencing factors. 3. Core Data: A central section with a Chart.js bar chart to visually compare the slight variations in observation times across Guadeloupe for a specific year, emphasizing the main date. 4. Practical Guide: A simple 3-step flowchart (HTML/CSS) for observation. 5. Cultural Depth: A two-column layout highlighting the stories from Egypt and the Dogon people, using a conceptual Donut chart to visualize the 50-year orbit of Sirius B. This tells a coherent story from what it is, to how to see it, to why it matters. -->
|
||||
<!-- Visualization & Content Choices: Big Number (Magnitude) -> Goal: Inform -> Viz: Large Text -> Justification: High impact for a key stat. Arcus Visionis -> Goal: Organize/Inform -> Viz: HTML/CSS Diagram -> Justification: Clear, custom visual without SVG. Observation Times -> Goal: Compare -> Viz: Bar Chart (Chart.js) -> Justification: Visually shows the minor time differences between locations, label wrapping handles long names. Dogon Orbit -> Goal: Inform/Organize -> Viz: Donut Chart (Chart.js) -> Justification: A strong visual hook for a key cultural concept. Flowchart -> Goal: Organize -> Viz: HTML/CSS -> Justification: Simple, clear process visualization without Mermaid JS. -->
|
||||
<!-- CONFIRMATION: NO SVG graphics used. NO Mermaid JS used. -->
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Inter', sans-serif;
|
||||
background-color: #0B2447; /* Deep Blue */
|
||||
color: #A5D7E8; /* Light Blue */
|
||||
}
|
||||
h1, h2, h3, .stat-number {
|
||||
font-family: 'Playfair Display', serif;
|
||||
}
|
||||
.card {
|
||||
background-color: #19376D; /* Medium Blue */
|
||||
border: 1px solid #576CBC;
|
||||
}
|
||||
.highlight {
|
||||
color: #FFFFFF;
|
||||
text-shadow: 0 0 8px rgba(165, 215, 232, 0.7);
|
||||
}
|
||||
.chart-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
height: 350px;
|
||||
max-height: 400px;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.chart-container {
|
||||
height: 400px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="antialiased">
|
||||
|
||||
<div class="max-w-4xl mx-auto p-4 md:p-8">
|
||||
|
||||
<header class="text-center my-12">
|
||||
<h1 class="text-4xl md:text-6xl font-bold text-white tracking-wider">LE LEVER HÉLIAQUE DE SIRIUS</h1>
|
||||
<p class="text-xl md:text-2xl mt-4 text-gray-300">Un rendez-vous cosmique entre Ciel, Science et Culture</p>
|
||||
</header>
|
||||
|
||||
<section class="grid grid-cols-1 md:grid-cols-2 gap-8 text-center my-16">
|
||||
<div class="card rounded-lg p-6">
|
||||
<p class="text-lg">Magnitude Apparente</p>
|
||||
<p class="stat-number text-6xl font-bold my-2 highlight">-1.46</p>
|
||||
<p class="text-sm">L'astre le plus brillant de notre ciel nocturne.</p>
|
||||
</div>
|
||||
<div class="card rounded-lg p-6">
|
||||
<p class="text-lg">Invisibilité Annuelle</p>
|
||||
<p class="stat-number text-6xl font-bold my-2 highlight">~70</p>
|
||||
<p class="text-sm">Jours où l'étoile est masquée par le Soleil (contexte égyptien).</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="science" class="my-16">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-center mb-8 text-white">La Danse Céleste</h2>
|
||||
<div class="card rounded-lg p-6 md:p-8">
|
||||
<p class="text-lg mb-6">Le lever héliaque est la première réapparition de Sirius à l'aube après sa "disparition". Sa visibilité dépend d'un angle précis, l'<strong class="highlight">Arcus Visionis</strong> : le Soleil doit être assez bas sous l'horizon pour que la lumière de l'étoile perce le crépuscule.</p>
|
||||
|
||||
<div class="border-2 border-dashed border-blue-400 rounded-lg p-4 text-center my-6">
|
||||
<div class="text-lg font-bold highlight">Arcus Visionis pour Sirius ≈ 9-10°</div>
|
||||
<div class="relative h-24 mt-4 flex items-end justify-center">
|
||||
<div class="absolute bottom-0 w-full h-px bg-cyan-200"></div>
|
||||
<div class="absolute bottom-0 text-cyan-200 font-bold">HORIZON</div>
|
||||
<div class="absolute" style="bottom: 20px; left: 25%;">
|
||||
<span class="text-4xl">★</span>
|
||||
<span class="block text-xs highlight">SIRIUS</span>
|
||||
</div>
|
||||
<div class="absolute" style="bottom: -25px; right: 25%;">
|
||||
<span class="text-4xl text-yellow-300">☀️</span>
|
||||
<span class="block text-xs text-yellow-300">SOLEIL</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-xs mt-8 text-gray-400">Le Soleil doit être à 9-10° sous l'horizon pour que Sirius devienne visible.</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mt-8 text-center">
|
||||
<div>
|
||||
<span class="text-4xl">✨</span>
|
||||
<h3 class="font-bold text-white mt-2">Magnitude</h3>
|
||||
<p class="text-sm">Plus une étoile est brillante, plus elle est facile à voir dans la lueur de l'aube.</p>
|
||||
</div>
|
||||
<div>
|
||||
<span class="text-4xl">🌍</span>
|
||||
<h3 class="font-bold text-white mt-2">Latitude</h3>
|
||||
<p class="text-sm">La position sur Terre change l'angle du lever et la durée du crépuscule.</p>
|
||||
</div>
|
||||
<div>
|
||||
<span class="text-4xl">🌫️</span>
|
||||
<h3 class="font-bold text-white mt-2">Atmosphère</h3>
|
||||
<p class="text-sm">L'humidité ou la brume peuvent "éteindre" l'étoile et retarder sa visibilité.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="predictions" class="my-16">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-center mb-2 text-white">L'Agenda Céleste 2025</h2>
|
||||
<p class="text-center mb-8 text-gray-300">La date clé pour le lever héliaque en Guadeloupe est le <strong class="highlight">22 Juillet</strong>. L'heure précise varie légèrement selon le site.</p>
|
||||
<div class="card rounded-lg p-6 md:p-8">
|
||||
<div class="chart-container">
|
||||
<canvas id="predictionsChart"></canvas>
|
||||
</div>
|
||||
<p class="text-xs text-center mt-4 text-gray-400">Ce graphique montre les variations de l'heure du lever pour chaque site en 2025. Notez comme les différences sont minimes, de l'ordre de quelques minutes seulement.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="culture" class="my-16">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-center mb-8 text-white">Miroir des Cultures</h2>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
<div class="card rounded-lg p-6">
|
||||
<h3 class="text-2xl font-bold text-white mb-4">Égypte : Sothis, Source de Vie</h3>
|
||||
<p>Pour les anciens Égyptiens, le lever héliaque de Sirius (Sothis) était l'événement majeur de l'année. Il annonçait la crue vitale du Nil, qui fertilisait les terres. Ce "retour" de l'étoile marquait le Nouvel An et symbolisait la renaissance, associée à la déesse Isis.</p>
|
||||
</div>
|
||||
<div class="card rounded-lg p-6 flex flex-col">
|
||||
<h3 class="text-2xl font-bold text-white mb-4">Dogon : La Science des Étoiles</h3>
|
||||
<p class="mb-4">Le peuple Dogon du Mali possède un savoir ancestral stupéfiant sur Sirius, décrivant une compagne invisible, "Po Tolo" (Sirius B), qui tourne autour de l'étoile principale en 50 ans.</p>
|
||||
<div class="flex-grow flex items-center justify-center h-48 md:h-auto">
|
||||
<div class="relative w-40 h-40">
|
||||
<canvas id="dogonChart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-xs text-center mt-2 text-gray-400">Visualisation du cycle orbital de 50 ans de Sirius B.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="howto" class="my-16">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-center mb-8 text-white">Votre Guide d'Observation</h2>
|
||||
<div class="flex flex-col md:flex-row items-center justify-center gap-4 md:gap-0 text-center">
|
||||
<div class="card p-6 rounded-lg w-full md:w-1/3">
|
||||
<div class="text-4xl font-bold highlight">1</div>
|
||||
<h3 class="font-bold text-white mt-2">Choisissez un Site</h3>
|
||||
<p class="text-sm mt-1">Trouvez un lieu avec un horizon Est dégagé, loin des lumières de la ville.</p>
|
||||
</div>
|
||||
<div class="h-8 md:h-auto w-px md:w-16 bg-blue-400 border-dashed border-l-2 md:border-l-0 md:border-b-2 border-blue-400"></div>
|
||||
<div class="card p-6 rounded-lg w-full md:w-1/3">
|
||||
<div class="text-4xl font-bold highlight">2</div>
|
||||
<h3 class="font-bold text-white mt-2">Préparez-vous</h3>
|
||||
<p class="text-sm mt-1">Utilisez un planétarium (Stellarium) pour repérer Sirius et arrivez 20 min en avance.</p>
|
||||
</div>
|
||||
<div class="h-8 md:h-auto w-px md:w-16 bg-blue-400 border-dashed border-l-2 md:border-l-0 md:border-b-2 border-blue-400"></div>
|
||||
<div class="card p-6 rounded-lg w-full md:w-1/3">
|
||||
<div class="text-4xl font-bold highlight">3</div>
|
||||
<h3 class="font-bold text-white mt-2">Soyez Patient</h3>
|
||||
<p class="text-sm mt-1">La météo peut changer la donne. Observez sur plusieurs jours.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-8 border-2 border-amber-400 bg-amber-500 bg-opacity-10 rounded-lg p-6 text-center text-amber-300">
|
||||
<h3 class="font-bold text-lg text-white">CONSEIL D'EXPERT : LA FENÊTRE D'OBSERVATION</h3>
|
||||
<p class="mt-2">Les dates calculées sont idéales. Pour maximiser vos chances, observez du <strong class="text-white">20 au 25 Juillet</strong>. La météo est le facteur clé !</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer class="text-center text-gray-400 text-sm mt-16 py-8 border-t border-gray-700">
|
||||
<p>Infographie inspirée du "Guide Astronomique et Culturel du Lever Héliaque de Sirius".</p>
|
||||
<p>Levez les yeux.</p>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const wrapLabel = (label) => {
|
||||
const maxLen = 16;
|
||||
if (label.length <= maxLen) return label;
|
||||
const words = label.replace(/ *\([^)]*\) */g, "").trim().split(' ');
|
||||
let currentLine = '';
|
||||
const lines = [];
|
||||
words.forEach(word => {
|
||||
if ((currentLine + ' ' + word).trim().length > maxLen) {
|
||||
lines.push(currentLine.trim());
|
||||
currentLine = word;
|
||||
} else {
|
||||
currentLine = (currentLine + ' ' + word).trim();
|
||||
}
|
||||
});
|
||||
lines.push(currentLine.trim());
|
||||
return lines;
|
||||
};
|
||||
|
||||
const tooltipTitleCallback = (tooltipItems) => {
|
||||
const item = tooltipItems[0];
|
||||
let label = item.chart.data.labels[item.dataIndex];
|
||||
if (Array.isArray(label)) {
|
||||
return label.join(' ');
|
||||
}
|
||||
return label;
|
||||
};
|
||||
|
||||
const renderPredictionsChart = () => {
|
||||
const ctx = document.getElementById('predictionsChart').getContext('2d');
|
||||
const locations = [
|
||||
"Pointe de la Grande Vigie", "Pointe des Châteaux", "Saint-Félix (Le Gosier)",
|
||||
"Duzer (Sainte-Rose)", "Grande Pointe (Trois-Rivières)", "Petit-Pérou", "Pointe du Vieux-Fort"
|
||||
];
|
||||
const times2025 = ["05:11", "05:12", "05:13", "05:13", "05:13", "05:14", "05:14"];
|
||||
|
||||
const dataInMinutes = times2025.map(t => {
|
||||
const [h, m] = t.split(':').map(Number);
|
||||
return (h * 60 + m) - (5 * 60 + 10);
|
||||
});
|
||||
|
||||
new Chart(ctx, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: locations.map(l => wrapLabel(l)),
|
||||
datasets: [{
|
||||
label: 'Heure du lever héliaque (2025)',
|
||||
data: dataInMinutes,
|
||||
backgroundColor: '#576CBC',
|
||||
borderColor: '#A5D7E8',
|
||||
borderWidth: 1
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
maintainAspectRatio: false,
|
||||
responsive: true,
|
||||
indexAxis: 'y',
|
||||
scales: {
|
||||
x: {
|
||||
beginAtZero: true,
|
||||
ticks: {
|
||||
color: '#A5D7E8',
|
||||
callback: function(value, index, values) {
|
||||
const totalMinutes = value + (5 * 60 + 10);
|
||||
const hours = Math.floor(totalMinutes / 60);
|
||||
const minutes = totalMinutes % 60;
|
||||
return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`;
|
||||
}
|
||||
},
|
||||
grid: { color: 'rgba(87, 108, 188, 0.3)' }
|
||||
},
|
||||
y: {
|
||||
ticks: { color: '#A5D7E8', font: { size: 10 } },
|
||||
grid: { display: false }
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
legend: { display: false },
|
||||
tooltip: {
|
||||
callbacks: {
|
||||
title: tooltipTitleCallback,
|
||||
label: function(context) {
|
||||
const totalMinutes = context.raw + (5 * 60 + 10);
|
||||
const hours = Math.floor(totalMinutes / 60);
|
||||
const minutes = totalMinutes % 60;
|
||||
return `Heure: ${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const renderDogonChart = () => {
|
||||
const ctx = document.getElementById('dogonChart').getContext('2d');
|
||||
new Chart(ctx, {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
labels: ['Cycle Orbital de Po Tolo (Sirius B)'],
|
||||
datasets: [{
|
||||
data: [50],
|
||||
backgroundColor: ['#A5D7E8'],
|
||||
borderColor: ['#19376D'],
|
||||
borderWidth: 2,
|
||||
hoverOffset: 4
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
maintainAspectRatio: false,
|
||||
responsive: true,
|
||||
cutout: '70%',
|
||||
plugins: {
|
||||
legend: { display: false },
|
||||
tooltip: {
|
||||
callbacks: {
|
||||
label: function(context) {
|
||||
return `Période: ${context.raw} ans`;
|
||||
}
|
||||
}
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: '50 ANS',
|
||||
color: '#FFFFFF',
|
||||
font: { size: 24, family: "'Playfair Display', serif" },
|
||||
position: 'bottom'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
renderPredictionsChart();
|
||||
renderDogonChart();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
+6
-11
@@ -1,20 +1,15 @@
|
||||
{
|
||||
"name": "gwada-sirius",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
"preview": "vite preview",
|
||||
"deploy": "npm run build && gh-pages -d dist"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
||||
"svelte": "^4.2.7",
|
||||
"vite": "^5.0.8"
|
||||
"vite": "^5.0.8",
|
||||
"gh-pages": "^6.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"three": "^0.160.0",
|
||||
"d3": "^7.8.5"
|
||||
}
|
||||
}
|
||||
"type": "module"
|
||||
}
|
||||
@@ -1,635 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Vague Planétaire de Sirius - Lever Héliaque 2025</title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
overflow: hidden;
|
||||
background: radial-gradient(circle at center, #0a192f 0%, #020c1b 100%);
|
||||
font-family: 'Arial', sans-serif;
|
||||
color: #ccd6f6;
|
||||
}
|
||||
|
||||
/* Contrôles */
|
||||
.controls {
|
||||
position: fixed;
|
||||
top: 1rem;
|
||||
right: 1rem;
|
||||
z-index: 10;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 0.75rem 1.5rem;
|
||||
background: linear-gradient(135deg, #ffd700 0%, #ffed4e 100%);
|
||||
color: #0a192f;
|
||||
border: none;
|
||||
border-radius: 25px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 15px rgba(255, 215, 0, 0.3);
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 20px rgba(255, 215, 0, 0.5);
|
||||
}
|
||||
|
||||
.btn.secondary {
|
||||
background: linear-gradient(135deg, #64ffda 0%, #64b5f6 100%);
|
||||
box-shadow: 0 4px 15px rgba(100, 255, 218, 0.3);
|
||||
}
|
||||
|
||||
/* Tooltip amélioré */
|
||||
#tooltip {
|
||||
position: absolute;
|
||||
padding: 12px 16px;
|
||||
background: rgba(10, 25, 47, 0.95);
|
||||
color: #ccd6f6;
|
||||
border-radius: 8px;
|
||||
pointer-events: none;
|
||||
display: none;
|
||||
z-index: 100;
|
||||
font-size: 0.9rem;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
|
||||
border: 1px solid rgba(255, 215, 0, 0.3);
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
#tooltip strong {
|
||||
color: #ffd700;
|
||||
font-size: 1.1rem;
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
#tooltip .date {
|
||||
color: #64ffda;
|
||||
}
|
||||
|
||||
/* Info Panel */
|
||||
.info-panel {
|
||||
position: fixed;
|
||||
bottom: 1rem;
|
||||
left: 1rem;
|
||||
background: rgba(10, 25, 47, 0.9);
|
||||
padding: 1.5rem;
|
||||
border-radius: 12px;
|
||||
backdrop-filter: blur(10px);
|
||||
border: 1px solid rgba(255, 215, 0, 0.2);
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.info-panel h2 {
|
||||
color: #ffd700;
|
||||
font-size: 1.2rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.info-panel p {
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.5;
|
||||
color: #8892b0;
|
||||
}
|
||||
|
||||
/* Loading */
|
||||
.loading {
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
text-align: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.loading-spinner {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border: 3px solid rgba(255, 215, 0, 0.3);
|
||||
border-top-color: #ffd700;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
margin-top: 1rem;
|
||||
color: #ffd700;
|
||||
}
|
||||
|
||||
/* Légende */
|
||||
.legend {
|
||||
position: fixed;
|
||||
top: 1rem;
|
||||
left: 1rem;
|
||||
background: rgba(10, 25, 47, 0.9);
|
||||
padding: 1rem;
|
||||
border-radius: 8px;
|
||||
border: 1px solid rgba(255, 215, 0, 0.2);
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.legend h3 {
|
||||
color: #ffd700;
|
||||
font-size: 1rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.legend-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
margin: 0.3rem 0;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.legend-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
/* Mobile responsive */
|
||||
@media (max-width: 768px) {
|
||||
.info-panel {
|
||||
max-width: 200px;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.legend {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.controls {
|
||||
top: 0.5rem;
|
||||
right: 0.5rem;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 0.5rem 1rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Loading Screen -->
|
||||
<div class="loading" id="loading">
|
||||
<div class="loading-spinner"></div>
|
||||
<div class="loading-text">Chargement de la carte stellaire...</div>
|
||||
</div>
|
||||
|
||||
<!-- Controls -->
|
||||
<div class="controls">
|
||||
<button class="btn" id="modeBtn">Mode Manuel</button>
|
||||
<button class="btn secondary" id="waveBtn">Afficher Vague</button>
|
||||
<button class="btn secondary" id="resetBtn">Réinitialiser</button>
|
||||
</div>
|
||||
|
||||
<!-- Tooltip -->
|
||||
<div id="tooltip"></div>
|
||||
|
||||
<!-- Legend -->
|
||||
<div class="legend">
|
||||
<h3>Lever Héliaque de Sirius</h3>
|
||||
<div class="legend-item">
|
||||
<div class="legend-icon" style="background: #ffd700;"></div>
|
||||
<span>Sites d'observation</span>
|
||||
</div>
|
||||
<div class="legend-item">
|
||||
<div class="legend-icon" style="background: #64ffda;"></div>
|
||||
<span>Vague de Sirius</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Info Panel -->
|
||||
<div class="info-panel">
|
||||
<h2>Wep Ronpet 2025</h2>
|
||||
<p>Le lever héliaque de Sirius marque le Nouvel An égyptien. Cette visualisation montre la progression de ce phénomène à travers le monde.</p>
|
||||
</div>
|
||||
|
||||
<!-- Three.js -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
|
||||
<script>
|
||||
// Configuration
|
||||
const config = {
|
||||
globeRadius: 1,
|
||||
markerSize: 0.08,
|
||||
waveSpeed: 0.001,
|
||||
autoRotateSpeed: 0.0005,
|
||||
cameraDistance: 3.2,
|
||||
colors: {
|
||||
marker: 0xffd700,
|
||||
wave: 0x64ffda,
|
||||
glow: 0xffd700,
|
||||
atmosphere: 0x64b5f6
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize Three.js
|
||||
const renderer = new THREE.WebGLRenderer({
|
||||
antialias: true,
|
||||
alpha: true,
|
||||
powerPreference: "high-performance"
|
||||
});
|
||||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||||
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
|
||||
renderer.shadowMap.enabled = true;
|
||||
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
|
||||
document.body.appendChild(renderer.domElement);
|
||||
|
||||
// Scene setup
|
||||
const scene = new THREE.Scene();
|
||||
scene.fog = new THREE.Fog(0x020c1b, 8, 20);
|
||||
|
||||
// Camera
|
||||
const camera = new THREE.PerspectiveCamera(
|
||||
45,
|
||||
window.innerWidth / window.innerHeight,
|
||||
0.1,
|
||||
1000
|
||||
);
|
||||
camera.position.z = config.cameraDistance;
|
||||
|
||||
// Lights
|
||||
const ambientLight = new THREE.AmbientLight(0x404040, 1.5);
|
||||
scene.add(ambientLight);
|
||||
|
||||
const sunLight = new THREE.DirectionalLight(0xffffff, 1);
|
||||
sunLight.position.set(5, 3, 5);
|
||||
sunLight.castShadow = true;
|
||||
scene.add(sunLight);
|
||||
|
||||
const backLight = new THREE.DirectionalLight(0x64b5f6, 0.3);
|
||||
backLight.position.set(-5, -3, -5);
|
||||
scene.add(backLight);
|
||||
|
||||
// Stars background
|
||||
const starsGeometry = new THREE.BufferGeometry();
|
||||
const starsCount = 5000;
|
||||
const starsPositions = new Float32Array(starsCount * 3);
|
||||
|
||||
for(let i = 0; i < starsCount * 3; i += 3) {
|
||||
const radius = 50 + Math.random() * 450;
|
||||
const theta = Math.random() * Math.PI * 2;
|
||||
const phi = Math.acos(Math.random() * 2 - 1);
|
||||
|
||||
starsPositions[i] = radius * Math.sin(phi) * Math.cos(theta);
|
||||
starsPositions[i + 1] = radius * Math.sin(phi) * Math.sin(theta);
|
||||
starsPositions[i + 2] = radius * Math.cos(phi);
|
||||
}
|
||||
|
||||
starsGeometry.setAttribute('position', new THREE.BufferAttribute(starsPositions, 3));
|
||||
|
||||
const starsMaterial = new THREE.PointsMaterial({
|
||||
color: 0xffffff,
|
||||
size: 0.5,
|
||||
transparent: true,
|
||||
opacity: 0.8,
|
||||
blending: THREE.AdditiveBlending
|
||||
});
|
||||
|
||||
const stars = new THREE.Points(starsGeometry, starsMaterial);
|
||||
scene.add(stars);
|
||||
|
||||
// Globe group
|
||||
const globeGroup = new THREE.Group();
|
||||
scene.add(globeGroup);
|
||||
|
||||
// Texture loader with error handling
|
||||
const loader = new THREE.TextureLoader();
|
||||
const textureUrls = {
|
||||
earth: 'https://raw.githubusercontent.com/jeromeetienne/threex.planets/master/images/earthmap1k.jpg',
|
||||
earthBump: 'https://raw.githubusercontent.com/jeromeetienne/threex.planets/master/images/earthbump1k.jpg',
|
||||
earthSpec: 'https://raw.githubusercontent.com/jeromeetienne/threex.planets/master/images/earthspec1k.jpg'
|
||||
};
|
||||
|
||||
// Sites data with accurate coordinates
|
||||
const sites = [
|
||||
{name: 'La Réunion', lat: -21.1151, lon: 55.5364, date: '27 Juin', time: '04:50', order: 1},
|
||||
{name: 'Kinshasa', lat: -4.4419, lon: 15.2663, date: '16 Juillet', time: '05:20', order: 2},
|
||||
{name: 'Guadeloupe', lat: 16.2650, lon: -61.5510, date: '22 Juillet', time: '05:10', order: 3},
|
||||
{name: 'Martinique', lat: 14.6415, lon: -61.0242, date: '23 Juillet', time: '05:08', order: 4},
|
||||
{name: 'Dakar', lat: 14.7167, lon: -17.4677, date: '23 Juillet', time: '05:15', order: 5},
|
||||
{name: 'Abidjan', lat: 5.3600, lon: -4.0083, date: '28 Juillet', time: '05:25', order: 6},
|
||||
{name: 'Lomé', lat: 6.1375, lon: 1.2123, date: '28 Juillet', time: '05:22', order: 7},
|
||||
{name: 'Accra', lat: 5.6037, lon: -0.1870, date: '28 Juillet', time: '05:23', order: 8},
|
||||
{name: 'Cotonou', lat: 6.3703, lon: 2.3912, date: '28 Juillet', time: '05:24', order: 9},
|
||||
{name: 'Lagos', lat: 6.5244, lon: 3.3792, date: '28 Juillet', time: '05:26', order: 10},
|
||||
{name: 'Yaoundé', lat: 3.8480, lon: 11.5021, date: '29 Juillet', time: '05:28', order: 11},
|
||||
{name: 'Libreville', lat: 0.4162, lon: 9.4673, date: '29 Juillet', time: '05:30', order: 12},
|
||||
{name: 'Brazzaville', lat: -4.2634, lon: 15.2429, date: '29 Juillet', time: '05:32', order: 13},
|
||||
{name: 'Kampala', lat: 0.3476, lon: 32.5825, date: '29 Juillet', time: '05:35', order: 14},
|
||||
{name: 'Nairobi', lat: -1.2921, lon: 36.8219, date: '30 Juillet', time: '05:37', order: 15},
|
||||
{name: 'Addis-Abeba', lat: 9.0320, lon: 38.7466, date: '26 Juillet', time: '05:18', order: 16},
|
||||
{name: 'Le Caire', lat: 30.0444, lon: 31.2357, date: '3 Août', time: '05:00', order: 17},
|
||||
{name: 'Paris', lat: 48.8566, lon: 2.3522, date: '12 Août', time: '05:45', order: 18}
|
||||
];
|
||||
|
||||
// Load textures and create globe
|
||||
Promise.all([
|
||||
new Promise((resolve, reject) => {
|
||||
loader.load(textureUrls.earth, resolve, undefined, reject);
|
||||
}),
|
||||
new Promise((resolve, reject) => {
|
||||
loader.load(textureUrls.earthBump, resolve, undefined, reject);
|
||||
}),
|
||||
new Promise((resolve, reject) => {
|
||||
loader.load(textureUrls.earthSpec, resolve, undefined, reject);
|
||||
})
|
||||
]).then(([earthMap, earthBump, earthSpec]) => {
|
||||
// Hide loading
|
||||
document.getElementById('loading').style.display = 'none';
|
||||
|
||||
// Create globe
|
||||
const globeGeometry = new THREE.SphereGeometry(config.globeRadius, 64, 64);
|
||||
const globeMaterial = new THREE.MeshPhongMaterial({
|
||||
map: earthMap,
|
||||
bumpMap: earthBump,
|
||||
bumpScale: 0.05,
|
||||
specularMap: earthSpec,
|
||||
specular: new THREE.Color(0x444444),
|
||||
shininess: 20
|
||||
});
|
||||
|
||||
const globe = new THREE.Mesh(globeGeometry, globeMaterial);
|
||||
globe.castShadow = true;
|
||||
globe.receiveShadow = true;
|
||||
globeGroup.add(globe);
|
||||
|
||||
// Atmosphere
|
||||
const atmosphereGeometry = new THREE.SphereGeometry(config.globeRadius * 1.1, 32, 32);
|
||||
const atmosphereMaterial = new THREE.ShaderMaterial({
|
||||
vertexShader: `
|
||||
varying vec3 vNormal;
|
||||
void main() {
|
||||
vNormal = normalize(normalMatrix * normal);
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
||||
}
|
||||
`,
|
||||
fragmentShader: `
|
||||
varying vec3 vNormal;
|
||||
void main() {
|
||||
float intensity = pow(0.7 - dot(vNormal, vec3(0.0, 0.0, 1.0)), 2.0);
|
||||
gl_FragColor = vec4(0.3, 0.6, 1.0, 1.0) * intensity;
|
||||
}
|
||||
`,
|
||||
blending: THREE.AdditiveBlending,
|
||||
side: THREE.BackSide
|
||||
});
|
||||
|
||||
const atmosphere = new THREE.Mesh(atmosphereGeometry, atmosphereMaterial);
|
||||
globeGroup.add(atmosphere);
|
||||
|
||||
// Wave system
|
||||
const waveGroup = new THREE.Group();
|
||||
globeGroup.add(waveGroup);
|
||||
|
||||
// Create wave rings
|
||||
const waveRings = [];
|
||||
for(let i = 0; i < 3; i++) {
|
||||
const radius = 1.01 + (i * 0.02); // Légèrement au-dessus du globe
|
||||
const waveGeometry = new THREE.TorusGeometry(radius, 0.05, 16, 100);
|
||||
waveGeometry.rotateX(Math.PI / 2); // Rotation pour que le torus soit horizontal
|
||||
|
||||
const waveMaterial = new THREE.MeshBasicMaterial({
|
||||
color: config.colors.wave,
|
||||
transparent: true,
|
||||
opacity: 0.4 - (i * 0.1),
|
||||
side: THREE.DoubleSide
|
||||
});
|
||||
|
||||
const wave = new THREE.Mesh(waveGeometry, waveMaterial);
|
||||
waveRings.push(wave);
|
||||
waveGroup.add(wave);
|
||||
}
|
||||
|
||||
// Markers
|
||||
const markersGroup = new THREE.Group();
|
||||
globeGroup.add(markersGroup);
|
||||
|
||||
// Create custom marker geometry (simplified ankh shape)
|
||||
const markerShape = new THREE.Shape();
|
||||
markerShape.moveTo(0, -0.5);
|
||||
markerShape.lineTo(0, 0.2);
|
||||
markerShape.moveTo(-0.3, 0);
|
||||
markerShape.lineTo(0.3, 0);
|
||||
markerShape.moveTo(0, 0.2);
|
||||
markerShape.absarc(0, 0.3, 0.2, Math.PI, 0, true);
|
||||
|
||||
const markerGeometry = new THREE.ShapeGeometry(markerShape);
|
||||
|
||||
// Add markers for each site
|
||||
sites.forEach(site => {
|
||||
// Conversion identique à l'exemple
|
||||
const latRad = site.lat * (Math.PI / 180);
|
||||
const lonRad = -site.lon * (Math.PI / 180);
|
||||
|
||||
const x = Math.cos(latRad) * Math.cos(lonRad);
|
||||
const y = Math.sin(latRad);
|
||||
const z = Math.cos(latRad) * Math.sin(lonRad);
|
||||
|
||||
// Marker group
|
||||
const markerGroup = new THREE.Group();
|
||||
|
||||
// Simple sphere marker comme dans l'exemple
|
||||
const markerGeometry = new THREE.SphereGeometry(0.015, 16, 16);
|
||||
const markerMaterial = new THREE.MeshBasicMaterial({
|
||||
color: config.colors.marker,
|
||||
emissive: 0x000000
|
||||
});
|
||||
const marker = new THREE.Mesh(markerGeometry, markerMaterial);
|
||||
|
||||
// Glow effect
|
||||
const glowGeometry = new THREE.SphereGeometry(0.025, 16, 16);
|
||||
const glowMaterial = new THREE.MeshBasicMaterial({
|
||||
color: config.colors.glow,
|
||||
transparent: true,
|
||||
opacity: 0.3,
|
||||
blending: THREE.AdditiveBlending
|
||||
});
|
||||
const glow = new THREE.Mesh(glowGeometry, glowMaterial);
|
||||
|
||||
markerGroup.add(marker);
|
||||
markerGroup.add(glow);
|
||||
|
||||
// Position directement sur le globe (rayon = 1)
|
||||
markerGroup.position.set(x, y, z);
|
||||
|
||||
markerGroup.userData = site;
|
||||
markersGroup.add(markerGroup);
|
||||
});
|
||||
|
||||
// Animation variables
|
||||
let autoRotate = true;
|
||||
let showWave = true;
|
||||
let mouseX = 0, mouseY = 0;
|
||||
let targetRotationX = 0, targetRotationY = 0;
|
||||
|
||||
// Controls
|
||||
const modeBtn = document.getElementById('modeBtn');
|
||||
const waveBtn = document.getElementById('waveBtn');
|
||||
const resetBtn = document.getElementById('resetBtn');
|
||||
|
||||
modeBtn.addEventListener('click', () => {
|
||||
autoRotate = !autoRotate;
|
||||
modeBtn.textContent = autoRotate ? 'Mode Manuel' : 'Mode Auto';
|
||||
});
|
||||
|
||||
waveBtn.addEventListener('click', () => {
|
||||
showWave = !showWave;
|
||||
waveGroup.visible = showWave;
|
||||
waveBtn.textContent = showWave ? 'Masquer Vague' : 'Afficher Vague';
|
||||
});
|
||||
|
||||
resetBtn.addEventListener('click', () => {
|
||||
targetRotationX = 0;
|
||||
targetRotationY = 0;
|
||||
camera.position.z = config.cameraDistance;
|
||||
});
|
||||
|
||||
// Mouse interaction
|
||||
let isDragging = false;
|
||||
const raycaster = new THREE.Raycaster();
|
||||
const mouse = new THREE.Vector2();
|
||||
const tooltip = document.getElementById('tooltip');
|
||||
|
||||
renderer.domElement.addEventListener('mousedown', () => {
|
||||
isDragging = true;
|
||||
renderer.domElement.style.cursor = 'grabbing';
|
||||
});
|
||||
|
||||
window.addEventListener('mouseup', () => {
|
||||
isDragging = false;
|
||||
renderer.domElement.style.cursor = 'grab';
|
||||
});
|
||||
|
||||
window.addEventListener('mousemove', (event) => {
|
||||
if (isDragging && !autoRotate) {
|
||||
targetRotationY += event.movementX * 0.005;
|
||||
targetRotationX += event.movementY * 0.005;
|
||||
targetRotationX = Math.max(-Math.PI/2, Math.min(Math.PI/2, targetRotationX));
|
||||
}
|
||||
|
||||
// Update mouse position for raycasting
|
||||
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
|
||||
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
|
||||
});
|
||||
|
||||
// Click detection
|
||||
renderer.domElement.addEventListener('click', (event) => {
|
||||
raycaster.setFromCamera(mouse, camera);
|
||||
const intersects = raycaster.intersectObjects(markersGroup.children, true);
|
||||
|
||||
if (intersects.length > 0) {
|
||||
const marker = intersects[0].object.parent;
|
||||
if (marker.userData && marker.userData.name) {
|
||||
const data = marker.userData;
|
||||
tooltip.innerHTML = `
|
||||
<strong>${data.name}</strong>
|
||||
<span class="date">${data.date} à ${data.time}</span>
|
||||
<br><small>Ordre: ${data.order}/${sites.length}</small>
|
||||
`;
|
||||
tooltip.style.left = event.clientX + 10 + 'px';
|
||||
tooltip.style.top = event.clientY - 30 + 'px';
|
||||
tooltip.style.display = 'block';
|
||||
|
||||
setTimeout(() => {
|
||||
tooltip.style.display = 'none';
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Zoom with mouse wheel
|
||||
renderer.domElement.addEventListener('wheel', (event) => {
|
||||
event.preventDefault();
|
||||
camera.position.z += event.deltaY * 0.002;
|
||||
camera.position.z = Math.max(2, Math.min(5, camera.position.z));
|
||||
});
|
||||
|
||||
// Animation loop
|
||||
function animate() {
|
||||
requestAnimationFrame(animate);
|
||||
|
||||
// Auto-rotate
|
||||
if (autoRotate) {
|
||||
targetRotationY += config.autoRotateSpeed;
|
||||
}
|
||||
|
||||
// Smooth rotation
|
||||
globeGroup.rotation.y += (targetRotationY - globeGroup.rotation.y) * 0.1;
|
||||
globeGroup.rotation.x += (targetRotationX - globeGroup.rotation.x) * 0.1;
|
||||
|
||||
// Animate wave
|
||||
if (showWave) {
|
||||
const time = Date.now() * 0.0002; // Même vitesse que l'exemple
|
||||
|
||||
// Oscillation entre sud et nord comme dans l'exemple
|
||||
const latAngle = Math.sin(time) * (Math.PI / 2);
|
||||
|
||||
waveRings.forEach((ring, i) => {
|
||||
const offset = i * 0.05; // Petit décalage entre les anneaux
|
||||
|
||||
// Position Y basée sur le sinus de l'angle de latitude
|
||||
ring.position.y = Math.sin(latAngle + offset);
|
||||
|
||||
// Scale basé sur le cosinus pour maintenir la forme circulaire
|
||||
const scale = Math.cos(latAngle + offset);
|
||||
ring.scale.set(scale, 1, scale);
|
||||
|
||||
// Opacité proportionnelle à l'échelle
|
||||
ring.material.opacity = (0.4 - (i * 0.1)) * Math.max(0.2, Math.abs(scale));
|
||||
});
|
||||
}
|
||||
|
||||
// Rotate stars slowly
|
||||
stars.rotation.y += 0.0001;
|
||||
|
||||
// Animate markers
|
||||
markersGroup.children.forEach((marker, i) => {
|
||||
const time = Date.now() * 0.001;
|
||||
const offset = i * 0.2;
|
||||
const scale = 1 + Math.sin(time + offset) * 0.1;
|
||||
marker.scale.setScalar(scale);
|
||||
});
|
||||
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
|
||||
animate();
|
||||
|
||||
}).catch(error => {
|
||||
console.error('Error loading textures:', error);
|
||||
document.getElementById('loading').innerHTML = `
|
||||
<div style="color: #ff6b6b;">Erreur de chargement</div>
|
||||
<div style="color: #8892b0; margin-top: 10px;">Vérifiez votre connexion internet</div>
|
||||
`;
|
||||
});
|
||||
|
||||
// Handle window resize
|
||||
window.addEventListener('resize', () => {
|
||||
camera.aspect = window.innerWidth / window.innerHeight;
|
||||
camera.updateProjectionMatrix();
|
||||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||||
});
|
||||
|
||||
// Initial cursor style
|
||||
renderer.domElement.style.cursor = 'grab';
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user