← Projects

Ring of Fire

2024 Passion Project Developer & Designer
  • Svelte
  • D3.js
  • Canvas API
  • GSAP

An interactive canvas-based scrollytelling story mapping 18,139 Philippine earthquakes from 2024 — from raw scatter to Mercator map, with animated transitions between five data views.

The Philippines sits on one of the most seismically active arcs on earth. In 2024 alone, 18,139 earthquakes were recorded — roughly 50 a day. Most go unfelt. Some reshape coastlines. This piece makes that relentless drumbeat of tectonic activity visible.

The challenge was scale: 18,000 points is too many for SVG without noticeable lag. Canvas handles it cleanly. Five scrollytelling steps move through five different framings of the same dataset — from raw scatter by magnitude, to geographic Mercator projection — each revealing a different dimension of the story.

Canvas animation showing 18,139 earthquakes transitioning between visualization states
All 18,139 earthquakes from 2024 — each point animated through five data views as the user scrolls.
Mercator projection showing earthquake distribution around Philippine fault lines
The geographic view — earthquake density maps directly onto the Philippine fault system and the Pacific Rim arc.
Animated transition between magnitude scatter and geographic map
The scatter-to-map transition — GSAP interpolates 18K points simultaneously at 60fps using typed Float32Array buffers.

Technical Approach

18,139 points in SVG would stutter. The solution is a Canvas 2D context with DPR scaling, typed array buffers (Float32Array for coordinates, Uint8ClampedArray for ImageData), and GSAP tweens running at 60fps. A seeded LCG random number generator keeps jitter stable across resizes. D3’s geoMercator handles the final geographic projection.

Highlights

  • Canvas 2D with DPR scaling — crisp rendering at any resolution
  • Five layout states: ring, grid, sorted grid, magnitude grid, Mercator map
  • GSAP time-based tweens interpolate all 18K points per frame
  • Seeded jitter via d3.randomLcg(42) — positions stay stable on resize
  • 5.7MB original JSON compacted to 367KB using array-of-arrays format