Project Write-up
This interactive visualization project brings to life historical hurricane tracks across the Atlantic and Gulf of America for June through November, leveraging NOAA's HURDAT2 dataset. Below is an overview of each phase of development:
Phase 1: Data Preparation
- Fetched the raw HURDAT2 data from NOAA and wrote a conversion script in JavaScript to parse the fixed-width format into structured JSON.
- Stored the processed JSON in
data/processed/hurdat2.json
for easy client-side access.
Phase 2: Interactive Map & Controls
- Built an interactive Leaflet map centered on the Atlantic and Gulf of America.
- Added a “Select Year” dropdown (1967–2024) and a “Show only major hurricanes” toggle overlaying the map in the bottom left.
- Disabled separate JS file references and inlined all custom code for simplicity.
Phase 3: Data Visualization with Charts
- Created three Chart.js visualizations showing:
- Storms per month (unique storms counted once per month).
- Average wind speed per month.
- Total storm track lengths per month.
- Filtered charts to only display the hurricane season (June–November).
- Ensured that each chart is rendered side-by-side in a responsive flex container.
Phase 4: Animation & Legend
- Implemented an animated replay that progressively draws each storm’s path.
- Added a color-coded legend in the top right corner for hurricane categories (Cat 1–5).
Phase 5: Dark Theme & Styling
- Swapped to Carto’s dark basemap for a cohesive nighttime aesthetic.
- Applied a full-page dark theme via CSS: dark backgrounds, light text, and semi-transparent overlays.
Key Code Snippets
Parsing Dates (YYYYMMDD):
function parseDate(dateString) {
const year = +dateString.slice(0,4);
const month = +dateString.slice(4,6) - 1;
const day = +dateString.slice(6,8);
return { year, month, day };
}
Counting Unique Storms per Month:
function updateStormsChart(data, year) {
const counts = Array(12).fill(0);
data.forEach(storm => {
const months = new Set();
storm.observations.forEach(obs => {
const d = parseDate(obs.date);
if (d.year === +year) months.add(d.month);
});
months.forEach(m => counts[m]++);
});
// build bar chart with counts.slice(5,11)
}