Refonte complète du globe avec texture réaliste et vague planétaire animée

This commit is contained in:
sucupira
2025-07-09 16:06:13 -04:00
parent 1cbabf7ce6
commit 4431d6d72d
7 changed files with 2173 additions and 57 deletions
+117
View File
@@ -0,0 +1,117 @@
# Notes sur le Projet Sirius en Guadeloupe
## 📋 Vue d'ensemble
J'ai créé une application web one-page avec Svelte qui combine les 3 pages HTML que vous aviez et enrichit le contenu avec les informations du PDF. L'application est moderne, mobile-first, avec un design panafricain/caribéen.
## 🏗️ Structure du projet
```
/home/sucupira/dev/Gwada-Sirius/
├── src/
│ ├── App.svelte # Composant principal
│ ├── app.css # Styles globaux avec patterns africains
│ ├── main.js # Point d'entrée
│ ├── components/ # Composants Svelte
│ │ ├── Navigation.svelte # Menu responsive
│ │ ├── Hero.svelte # Section héro avec animation d'étoiles
│ │ ├── About.svelte # Introduction à Sirius
│ │ ├── Predictions.svelte # Calculateur interactif
│ │ ├── Science.svelte # Explication scientifique
│ │ ├── Culture.svelte # Héritage culturel
│ │ ├── Observatory.svelte # Guide d'observation
│ │ ├── Globe.svelte # Visualisation globe (Canvas 2D)
│ │ └── Footer.svelte # Pied de page
│ └── data/
│ └── predictions.js # Données des prédictions
├── package.json
├── vite.config.js
├── index.html
├── README.md
├── .gitignore
└── start.sh # Script de démarrage rapide
```
## 🎨 Design et fonctionnalités
### Palette de couleurs panafricaine :
- **Or (#FFD700)** : Couleur principale, représente Sirius et le soleil
- **Rouge profond (#DC143C)** : Accent
- **Vert forêt (#228B22)** : Nature
- **Bleu nuit (#1a1a2e)** : Fond, ciel nocturne
### Patterns africains intégrés :
- **Kente** : Motif géométrique en diagonale
- **Bogolan** : Cercles et points
- **Adinkra** : Motifs symboliques
### Sections principales :
1. **Hero** : Animation d'étoiles interactive avec effet parallaxe
2. **About** : Introduction avec cartes d'information
3. **Predictions** : Calculateur interactif avec sélecteurs
4. **Science** : Tabs pour explorer la mécanique céleste
5. **Culture** : Timeline et cartes culturelles
6. **Observatory** : Guide pratique étape par étape
7. **Globe** : Visualisation 2D animée (plus léger que Three.js)
## 🚀 Pour démarrer
```bash
cd /home/sucupira/dev/Gwada-Sirius
./start.sh
```
Ou manuellement :
```bash
npm install
npm run dev
```
## 📱 Responsive Design
- Mobile-first approach
- Menu hamburger pour mobile
- Grilles flexibles
- Tailles de police adaptatives avec clamp()
## ⚡ Performance
- Svelte compile en vanilla JS (pas de runtime)
- Canvas 2D au lieu de Three.js pour le globe
- Lazy loading des animations avec IntersectionObserver
- CSS optimisé avec variables custom properties
## 🔄 Améliorations possibles
1. **Ajouter un compte à rebours dynamique** jusqu'au 22 juillet
2. **Intégrer une API météo** pour les prévisions
3. **Ajouter des sons ambiants** africains/caribéens
4. **Mode sombre/clair** automatique selon l'heure
5. **PWA** pour installation mobile
6. **Partage social** avec meta tags optimisés
7. **Multilingue** (Français, Créole, Anglais)
8. **Animations GSAP** pour plus de fluidité
## 📦 Build pour production
```bash
npm run build
# Les fichiers seront dans dist/
```
## 🌐 Déploiement
Peut être déployé facilement sur :
- Netlify (drag & drop du dossier dist)
- Vercel
- GitHub Pages
- Surge.sh
## 💡 Points techniques importants
1. **Données astronomiques** : Toutes les prédictions sont stockées dans `src/data/predictions.js`
2. **Animations** : Utilisation de CSS animations et requestAnimationFrame
3. **État** : Gestion simple avec les stores Svelte (pas de store global pour l'instant)
4. **SEO** : Ajouter les meta tags appropriés dans index.html
Le projet est maintenant prêt et fonctionnel ! Vous pouvez le personnaliser selon vos besoins.
+1692
View File
File diff suppressed because it is too large Load Diff
+8 -2
View File
@@ -42,14 +42,20 @@
<div class="container">
<div class="section-header" class:visible>
<h2>Sirius, Wep Ronpet</h2>
<h2>Sirius et Wep Ronpet</h2>
<p class="section-subtitle">
Le Nouvel An Cosmique des Anciens
L'Ouverture de l'Année - Le Nouvel An Cosmique des Anciens Égyptiens
</p>
</div>
<div class="about-content" class:visible>
<div class="about-text">
<p>
<strong>Wep Ronpet</strong> - "l'Ouverture de l'Année" en égyptien ancien -
marquait le jour le plus sacré du calendrier égyptien. Ce jour correspondait
au lever héliaque de Sirius, quand l'étoile réapparaissait à l'aube après
70 jours d'invisibilité.
</p>
<p>
Le lever héliaque de Sirius n'est pas qu'un simple phénomène astronomique.
C'est un rendez-vous millénaire entre l'humanité et le cosmos, un moment où
+7 -2
View File
@@ -91,8 +91,6 @@
gap: var(--spacing-lg);
margin-bottom: var(--spacing-lg);
}
font-size: 1.5rem;
}
.countdown {
display: flex;
@@ -130,6 +128,13 @@
opacity: 0.8;
}
.social-links {
display: flex;
gap: 1rem;
margin-top: 1rem;
font-size: 1.5rem;
}
@media (max-width: 768px) {
.footer-content {
grid-template-columns: 1fr;
+316 -53
View File
@@ -24,7 +24,6 @@
});
function initGlobe() {
// Version simplifiée avec Canvas 2D au lieu de Three.js pour la performance
const ctx = canvas.getContext('2d');
const width = canvas.width = canvas.offsetWidth;
const height = canvas.height = canvas.offsetHeight;
@@ -33,74 +32,282 @@
const centerY = height / 2;
const radius = Math.min(width, height) * 0.35;
let rotation = 0;
let rotation = 2.5; // Commencer avec l'Atlantique visible
let zoom = 1;
let isDragging = false;
let lastMouseX = 0;
let waveAnimation = 0;
// Données des lieux dans l'ordre chronologique
const locations = [
{ name: 'Guadeloupe', lat: 16.2650, lon: -61.5510, date: '22 Juillet' },
{ name: 'Martinique', lat: 14.6415, lon: -61.0242, date: '23 Juillet' },
{ name: 'Dakar', lat: 14.7167, lon: -17.4677, date: '23 Juillet' },
{ name: 'Le Caire', lat: 30.0444, lon: 31.2357, date: '3 Août' },
{ name: 'Kinshasa', lat: -4.4419, lon: 15.2663, date: '16 Juillet' }
{ name: 'La Réunion', lat: -21.1151, lon: 55.5364, date: '27 Juin', day: 178 },
{ name: 'Kinshasa', lat: -4.4419, lon: 15.2663, date: '16 Juillet', day: 197 },
{ name: 'Guadeloupe', lat: 16.2650, lon: -61.5510, date: '22 Juillet', day: 203 },
{ name: 'Martinique', lat: 14.6415, lon: -61.0242, date: '23 Juillet', day: 204 },
{ name: 'Dakar', lat: 14.7167, lon: -17.4677, date: '23 Juillet', day: 204 },
{ name: 'Abidjan', lat: 5.3600, lon: -4.0083, date: '28 Juillet', day: 209 },
{ name: 'Le Caire', lat: 30.0444, lon: 31.2357, date: '3 Août', day: 215 },
{ name: 'Paris', lat: 48.8566, lon: 2.3522, date: '12 Août', day: 224 }
];
function draw() {
ctx.clearRect(0, 0, width, height);
// Gérer le zoom
canvas.addEventListener('wheel', (e) => {
e.preventDefault();
zoom += e.deltaY * -0.001;
zoom = Math.min(Math.max(0.5, zoom), 2);
});
// Globe
ctx.beginPath();
ctx.arc(centerX, centerY, radius, 0, Math.PI * 2);
ctx.strokeStyle = 'rgba(255, 215, 0, 0.3)';
ctx.lineWidth = 2;
ctx.stroke();
// Gérer la rotation avec la souris
canvas.addEventListener('mousedown', (e) => {
isDragging = true;
lastMouseX = e.clientX;
});
// Méridiens et parallèles
ctx.strokeStyle = 'rgba(255, 215, 0, 0.1)';
window.addEventListener('mousemove', (e) => {
if (isDragging) {
const deltaX = e.clientX - lastMouseX;
rotation -= deltaX * 0.01; // Inverser pour tourner dans le bon sens
lastMouseX = e.clientX;
}
});
window.addEventListener('mouseup', () => {
isDragging = false;
});
// Support tactile
canvas.addEventListener('touchstart', (e) => {
isDragging = true;
lastMouseX = e.touches[0].clientX;
e.preventDefault();
});
canvas.addEventListener('touchmove', (e) => {
if (isDragging && e.touches.length === 1) {
const deltaX = e.touches[0].clientX - lastMouseX;
rotation -= deltaX * 0.01;
lastMouseX = e.touches[0].clientX;
e.preventDefault();
}
});
canvas.addEventListener('touchend', () => {
isDragging = false;
});
// Dessiner les continents simplifiés
function drawContinents(ctx, centerX, centerY, radius, rotation) {
ctx.save();
ctx.globalAlpha = 0.3;
ctx.strokeStyle = '#4a7c59';
ctx.fillStyle = '#2d5f3f';
ctx.lineWidth = 1;
for (let i = 0; i < 6; i++) {
const angle = (i / 6) * Math.PI;
ctx.beginPath();
ctx.ellipse(centerX, centerY, radius * Math.cos(angle), radius, 0, 0, Math.PI * 2);
ctx.stroke();
}
// Afrique (très simplifiée)
const africa = [
{lat: 37, lon: 10}, {lat: 35, lon: -5}, {lat: 30, lon: -17},
{lat: 15, lon: -17}, {lat: 5, lon: -10}, {lat: -5, lon: 8},
{lat: -15, lon: 15}, {lat: -25, lon: 20}, {lat: -35, lon: 20},
{lat: -35, lon: 30}, {lat: -25, lon: 35}, {lat: -10, lon: 40},
{lat: 5, lon: 45}, {lat: 15, lon: 45}, {lat: 30, lon: 35}, {lat: 37, lon: 10}
];
drawLandmass(africa);
// Amérique du Sud
const southAmerica = [
{lat: 10, lon: -60}, {lat: 5, lon: -50}, {lat: -5, lon: -35},
{lat: -15, lon: -38}, {lat: -25, lon: -48}, {lat: -35, lon: -58},
{lat: -45, lon: -65}, {lat: -55, lon: -70}, {lat: -45, lon: -73},
{lat: -35, lon: -72}, {lat: -25, lon: -70}, {lat: -15, lon: -75},
{lat: -5, lon: -78}, {lat: 5, lon: -77}, {lat: 10, lon: -60}
];
drawLandmass(southAmerica);
// Points des villes
locations.forEach((loc, i) => {
const phi = (90 - loc.lat) * Math.PI / 180;
const theta = (loc.lon + rotation) * Math.PI / 180;
// Europe (simplifiée)
const europe = [
{lat: 60, lon: 25}, {lat: 55, lon: 10}, {lat: 50, lon: -5},
{lat: 45, lon: -5}, {lat: 40, lon: -10}, {lat: 36, lon: -6},
{lat: 40, lon: 0}, {lat: 45, lon: 10}, {lat: 50, lon: 20},
{lat: 55, lon: 30}, {lat: 60, lon: 25}
];
drawLandmass(europe);
function drawLandmass(points) {
const coords = points.map(p => {
const phi = (90 - p.lat) * Math.PI / 180;
const theta = (p.lon - rotation * 57.3) * Math.PI / 180;
const x = radius * Math.sin(phi) * Math.cos(theta);
const y = radius * Math.cos(phi);
const z = radius * Math.sin(phi) * Math.sin(theta);
// Ne dessiner que si visible (z > 0)
return { x: centerX + x, y: centerY - y, z: z };
});
// Ne dessiner que si au moins un point est visible
if (coords.some(c => c.z > -radius * 0.5)) {
ctx.beginPath();
coords.forEach((c, i) => {
if (i === 0) ctx.moveTo(c.x, c.y);
else ctx.lineTo(c.x, c.y);
});
ctx.closePath();
if (coords[0].z > 0) {
ctx.fill();
}
ctx.stroke();
}
}
ctx.restore();
}
function draw() {
ctx.clearRect(0, 0, width, height);
const currentRadius = radius * zoom;
// Océan (fond du globe)
const oceanGradient = ctx.createRadialGradient(
centerX - currentRadius * 0.3,
centerY - currentRadius * 0.3,
0,
centerX,
centerY,
currentRadius
); oceanGradient.addColorStop(0, '#2c5aa0');
oceanGradient.addColorStop(0.7, '#1e3a8a');
oceanGradient.addColorStop(1, '#0f172a');
ctx.beginPath();
ctx.arc(centerX, centerY, currentRadius, 0, Math.PI * 2);
ctx.fillStyle = oceanGradient;
ctx.fill();
// Grille de méridiens et parallèles
ctx.strokeStyle = 'rgba(100, 200, 255, 0.1)';
ctx.lineWidth = 1;
// Méridiens (longitudes)
for (let lon = -180; lon <= 180; lon += 30) {
ctx.beginPath();
for (let lat = -90; lat <= 90; lat += 5) {
const phi = (90 - lat) * Math.PI / 180;
const theta = (lon - rotation * 57.3) * Math.PI / 180;
const x = currentRadius * Math.sin(phi) * Math.cos(theta);
const y = currentRadius * Math.cos(phi);
const z = currentRadius * Math.sin(phi) * Math.sin(theta);
if (z > 0) {
const screenX = centerX + x;
const screenY = centerY - y;
// Point
if (lat === -90) ctx.moveTo(screenX, screenY);
else ctx.lineTo(screenX, screenY);
}
}
ctx.stroke();
}
// Parallèles (latitudes)
for (let lat = -60; lat <= 60; lat += 30) {
ctx.beginPath();
ctx.arc(screenX, screenY, 5, 0, Math.PI * 2);
ctx.fillStyle = '#FFD700';
ctx.fill();
for (let lon = -180; lon <= 180; lon += 5) {
const phi = (90 - lat) * Math.PI / 180;
const theta = (lon - rotation * 57.3) * Math.PI / 180;
// Glow
const gradient = ctx.createRadialGradient(screenX, screenY, 0, screenX, screenY, 20);
gradient.addColorStop(0, 'rgba(255, 215, 0, 0.8)');
gradient.addColorStop(1, 'rgba(255, 215, 0, 0)');
ctx.fillStyle = gradient;
ctx.fillRect(screenX - 20, screenY - 20, 40, 40);
const x = currentRadius * Math.sin(phi) * Math.cos(theta);
const y = currentRadius * Math.cos(phi);
const z = currentRadius * Math.sin(phi) * Math.sin(theta);
if (z > 0) {
const screenX = centerX + x;
const screenY = centerY - y;
if (lon === -180) ctx.moveTo(screenX, screenY);
else ctx.lineTo(screenX, screenY);
}
}
ctx.stroke();
}
// Dessiner les continents
drawContinents(ctx, centerX, centerY, currentRadius, rotation);
// Bordure du globe
ctx.beginPath();
ctx.arc(centerX, centerY, currentRadius, 0, Math.PI * 2);
ctx.strokeStyle = 'rgba(255, 215, 0, 0.3)';
ctx.lineWidth = 2;
ctx.stroke();
// Dessiner la vague de progression
waveAnimation += 0.02;
const waveDay = ((Math.sin(waveAnimation) + 1) / 2) * 46 + 178; // Entre jour 178 et 224
// Dessiner les points et la vague
locations.forEach((loc, i) => {
const phi = (90 - loc.lat) * Math.PI / 180;
const theta = (loc.lon - rotation * 57.3) * Math.PI / 180;
const x = currentRadius * Math.sin(phi) * Math.cos(theta);
const y = currentRadius * Math.cos(phi);
const z = currentRadius * Math.sin(phi) * Math.sin(theta);
if (z > -currentRadius * 0.3) {
const screenX = centerX + x;
const screenY = centerY - y;
// Calculer l'état selon la vague
const isActive = waveDay >= loc.day;
const isNear = Math.abs(waveDay - loc.day) < 5;
// Effet de vague
if (isNear && z > 0) {
const waveSize = 40 * (1 - Math.abs(waveDay - loc.day) / 5);
const waveGradient = ctx.createRadialGradient(screenX, screenY, 0, screenX, screenY, waveSize);
waveGradient.addColorStop(0, 'rgba(255, 215, 0, 0.8)');
waveGradient.addColorStop(0.5, 'rgba(255, 215, 0, 0.3)');
waveGradient.addColorStop(1, 'rgba(255, 215, 0, 0)');
ctx.fillStyle = waveGradient;
ctx.fillRect(screenX - waveSize, screenY - waveSize, waveSize * 2, waveSize * 2);
}
// Point
const opacity = z > 0 ? 1 : 0.3;
ctx.globalAlpha = opacity;
ctx.beginPath();
ctx.arc(screenX, screenY, isActive ? 6 : 4, 0, Math.PI * 2);
ctx.fillStyle = isActive ? '#FFD700' : '#666666';
ctx.fill();
ctx.strokeStyle = isActive ? '#FFFFFF' : '#999999';
ctx.lineWidth = 2;
ctx.stroke();
// Label
ctx.fillStyle = '#FFD700';
ctx.font = '12px Inter';
if (z > 0) {
ctx.fillStyle = isActive ? '#FFD700' : '#999999';
ctx.font = `${12 * zoom}px Inter`;
ctx.textAlign = 'center';
ctx.fillText(loc.name, screenX, screenY - 15);
ctx.fillText(loc.date, screenX, screenY + 25);
ctx.fillText(loc.name, screenX, screenY - 12);
ctx.font = `${10 * zoom}px Inter`;
ctx.fillText(loc.date, screenX, screenY + 22);
}
ctx.globalAlpha = 1;
}
});
rotation += 0.005;
// Légende
ctx.fillStyle = '#FFD700';
ctx.font = '16px Inter';
ctx.textAlign = 'left';
ctx.fillText('🌟 Vague du Lever Héliaque de Sirius', 20, 30); ctx.font = '12px Inter';
ctx.fillStyle = '#CCCCCC';
const currentDate = locations.find(l => Math.abs(l.day - waveDay) < 2);
if (currentDate) {
ctx.fillText(`Animation : ${currentDate.name} - ${currentDate.date}`, 20, 50);
}
// Rotation automatique lente
if (!isDragging) {
rotation += 0.002;
}
requestAnimationFrame(draw);
}
@@ -120,25 +327,42 @@
<div class="globe-container" class:visible>
<canvas bind:this={canvas} class="globe-canvas"></canvas>
<div class="globe-controls">
<p>🖱️ Glisser pour tourner | 🔍 Molette pour zoomer</p>
</div>
<div class="globe-info">
<div class="info-card card">
<h3>Le Phénomène Global</h3>
<p>
Le lever héliaque de Sirius n'est pas simultané sur Terre.
Il progresse comme une vague, commençant dans l'hémisphère sud
pour remonter vers le nord. Cette progression suit la géométrie
céleste et dépend de la latitude de chaque lieu.
Il progresse comme une vague dorée, commençant dans l'océan Indien
(La Réunion en juin) pour traverser l'Afrique, les Caraïbes,
puis remonter vers l'Europe (Paris en août).
</p>
<p>
En Guadeloupe, nous sommes privilégiés : le phénomène se produit
fin juillet, dans des conditions météorologiques généralement favorables.
Cette progression suit la géométrie céleste : plus on va vers le nord,
plus le phénomène se produit tard. La Guadeloupe se trouve au cœur
de cette vague en juillet, bénéficiant de conditions idéales.
</p>
<div class="timeline-mini">
<div class="timeline-item-mini">
<span class="date">27 Juin</span>
<span class="location">La Réunion</span>
</div>
<div class="timeline-item-mini">
<span class="date">22-23 Juillet</span>
<span class="location">Guadeloupe & Caraïbes</span>
</div>
<div class="timeline-item-mini">
<span class="date">12 Août</span>
<span class="location">Paris</span>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<style>
.globe-section {
padding: var(--spacing-xl) 0;
@@ -163,9 +387,22 @@
.globe-canvas {
width: 100%;
height: 400px;
height: 500px;
border-radius: 20px;
background: rgba(0, 0, 0, 0.5);
background: radial-gradient(circle at center, #0a192f 0%, #020c1b 100%);
cursor: grab;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.5);
}
.globe-canvas:active {
cursor: grabbing;
}
.globe-controls {
text-align: center;
margin-top: 0.5rem;
font-size: 0.9rem;
color: var(--color-primary);
opacity: 0.7;
}
.info-card h3 {
@@ -178,13 +415,39 @@
line-height: 1.8;
}
.timeline-mini {
margin-top: 1.5rem;
padding: 1rem;
background: rgba(255, 215, 0, 0.1);
border-radius: 10px;
}
.timeline-item-mini {
display: flex;
justify-content: space-between;
padding: 0.5rem 0;
border-bottom: 1px solid rgba(255, 215, 0, 0.2);
}
.timeline-item-mini:last-child {
border-bottom: none;
}
.timeline-item-mini .date {
font-weight: 600;
color: var(--color-primary);
}
.timeline-item-mini .location {
color: var(--color-light);
}
@media (max-width: 768px) {
.globe-container {
grid-template-columns: 1fr;
}
.globe-canvas {
height: 300px;
height: 400px;
}
}
</style>
+14 -2
View File
@@ -83,7 +83,10 @@
<span class="title-line">en Guadeloupe</span>
</h1>
<p class="hero-subtitle">
Le rendez-vous cosmique entre Ciel, Science et Culture
Wep Ronpet - L'Ouverture de l'Année Cosmique
</p>
<p class="hero-description">
Le rendez-vous millénaire entre Ciel, Science et Culture
</p>
<p class="hero-date">
Lever héliaque : <strong>22 Juillet 2025</strong>
@@ -171,11 +174,20 @@
.hero-subtitle {
font-size: clamp(1.2rem, 3vw, 1.5rem);
color: var(--color-primary);
margin-bottom: 1rem;
font-family: var(--font-heading);
margin-bottom: 0.5rem;
animation: fadeInUp 1s ease-out 0.4s;
animation-fill-mode: both;
}
.hero-description {
font-size: clamp(1rem, 2.5vw, 1.2rem);
color: var(--color-light);
margin-bottom: 1rem;
animation: fadeInUp 1s ease-out 0.5s;
animation-fill-mode: both;
}
.hero-date {
font-size: 1.2rem;
margin-bottom: 2rem;
Executable
+21
View File
@@ -0,0 +1,21 @@
#!/bin/bash
echo "🌟 Sirius en Guadeloupe - Démarrage du projet"
echo "============================================="
# Vérifier si node_modules existe
if [ ! -d "node_modules" ]; then
echo "📦 Installation des dépendances..."
npm install
fi
echo "🚀 Lancement du serveur de développement..."
echo "📱 L'application sera accessible sur http://localhost:5173"
echo ""
echo "Commandes disponibles:"
echo " - Ctrl+C : Arrêter le serveur"
echo " - npm run build : Créer une version de production"
echo " - npm run preview : Prévisualiser la version de production"
echo ""
npm run dev