Copied to Clipboard
Features at a Glance
-
π Animated SVG Globe β Custom-built with organic Bezier-path continents, real-time ocean color shifting, smog overlays, fire particles, cloud layers, and polar ice caps β all reacting live to your slider input
-
π Earth's Emotional Face β The globe has animated eyes, eyebrows, cheeks, and a mouth that morph across 5 emotional states as Earth Health changes β from rosy-cheeked happiness to X-eyes and a wobbling distressed mouth at near-extinction
-
π Orbiting Moon with Personality β A textured SVG moon orbits the globe in a proper elliptical path, correctly rendering behind Earth on the far side and in front on the near side. The Moon has its own reactive face β it gets increasingly worried with sweat drops as Earth's condition worsens
-
π Earth Day Banner β A vertical side panel with a drop-bounce letter reveal animation and SVG confetti explosion (click to trigger again!) celebrating April 22
-
6 Environmental Sliders β Temperature (β2Β°C to +10Β°C), Sea Level, Forest Cover, Pollution, Ice Caps, and Clean Energy
-
Earth Health Score β A unified 0β1000 vitality meter with reactive color-coded status labels (from Thriving Paradise to Near Extinction)
-
Real-time Population Ticker β A frame-by-frame world population counter (8.2B baseline) that ticks up or down based on current planetary health
-
Event Feed β Contextual alerts that surface climate events based on your settings
-
10-Year Simulation Engine β Year-by-year population projection with animated reveal and color-coded survival verdict
-
Zero Dependencies β Pure Vanilla HTML5, CSS3, and JS. No frameworks, no libraries, no build step.
How I Built It
This was built using Antigravity β a vibe coding tool powered by Google Gemini 2.0 Pro β with a deliberate "Single File β Split Architecture" workflow.
The Globe Rendering Pipeline
The globe is a layered SVG with groups for ocean, land, clouds, ice caps, smog, fire, and now a face-group on top. Each requestAnimationFrame tick, the renderer recomputes ocean color, shifts atmosphere hue, translates continents and clouds for rotation, calculates biome visibility, and renders fire particles when conditions are right.
Earth's Emotional Face
The face is a set of SVG elements (<ellipse> eyes, <rect> brows, <path> mouth) that get imperatively updated on every slider change. The calcScore() result drives which expression state is applied β 5 tiers from happy to dying. Eyebrows rotate via CSS transform, the mouth path d attribute changes shape, and at critical danger the mouth switches to a wavy path with a wobbleMouth CSS keyframe animation for that extra distress effect.
The Orbiting Moon
The moon orbits on an ellipse (rx: 155, ry: 45) centered on the globe using a moonAngle counter that increments each frame. The depth-sorting trick: if moonY > 130 (front half of orbit), the moon group is appendChild-ed to the end of the SVG so it renders above Earth; otherwise it's insertBefore the ocean layer so it appears behind. The moon's own pupils shift horizontally to always look away from Earth β a small touch that makes it feel alive. Animated sweat drops (slideSweat keyframe) appear on the moon's face when Earth's score drops below 50.
The Simulation Math
The 10-year engine applies weighted penalties per variable per year:
let growth = 80; // Base +80M/yr
growth -= (temp / 10) * 200;
growth -= (poll / 100) * 150;
growth -= (1 - forest / 100) * 100;
growth -= (sea / 10) * 80;
growth -= (1 - energy / 100) * 60;
growth -= (1 - ice / 100) * 40;
The UI
Orbitron + Space Mono for a command-center sci-fi feel. CSS starfield background, reactive glow shadows on the globe, and all slider tracks fill dynamically with the current condition color.
simulation result
Challenges
SVG Depth Sorting for the Moon β SVG renders in document order, not by Z-index. Getting the moon to appear behind Earth on the back half of its orbit required dynamically re-inserting the moon group into the SVG DOM each frame based on its Y position.
Face Expressiveness in SVG β Making emotions readable at 260px required careful tuning of path coordinates. The eyebrow rotation pivot point matters a lot β transform-origin had to be set relative to each brow's center, not the SVG origin.
Balancing the Simulation Math β The formula needed to feel consequential without being instantly catastrophic. The current weights were iterated ~8 times to hit the right dramatic tension.
Single-File 60fps Performance β Keeping the entire render loop smooth without any virtual DOM or external state management meant being surgical about what gets recomputed each frame vs. what's event-driven on slider input.
Prize Categories
π Best Use of Google Gemini β Built using Antigravity, powered by Google Gemini 2.0 Pro as its underlying model for code generation and iteration.