Add Mapbox GL JS 3D globe web-enhanced infinite loop system
Extends the web-enhanced infinite loop to support Mapbox GL JS globe visualizations. Enables progressive learning of Mapbox techniques through curated documentation, examples, and tutorials. Key additions: - Mapbox globe visualization specification with progressive pathways - Curated URL strategy covering foundation → expert Mapbox techniques - Demo: Global population distribution with 100 cities on 3D globe - Multi-file structure: HTML, JS, data, documentation per iteration System features: - Globe projection with atmosphere and space effects - Data-driven styling with Mapbox expressions - Interactive layers (heatmap, circle, fill, extrusion) - Progressive complexity: single layer → multi-layer → 3D → WebGL - 40+ curated Mapbox documentation URLs for systematic learning Demo visualization includes: - 3D rotating globe with satellite imagery - 100 major cities with population-based sizing and colors - Auto-rotation with smart pause/resume on interaction - Interactive popups, navigation controls, fullscreen mode - Professional UI with legends and overlays Generalizable to any geographic/spatial data visualization domain where progressive Mapbox GL JS learning creates increasingly sophisticated interactive globe experiences. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
0d28f88fcc
commit
b64c0d997b
|
|
@ -0,0 +1,341 @@
|
|||
# CLAUDE.md
|
||||
|
||||
Development guidelines for the Mapbox Globe Visualization project.
|
||||
|
||||
## Running the Visualization
|
||||
|
||||
### Local Development Server
|
||||
|
||||
Start a local server from the project root:
|
||||
|
||||
```bash
|
||||
# Python 3 (recommended)
|
||||
python -m http.server 8000
|
||||
|
||||
# Python 2
|
||||
python -m SimpleHTTPServer 8000
|
||||
|
||||
# Node.js
|
||||
npx http-server -p 8000
|
||||
|
||||
# PHP
|
||||
php -S localhost:8000
|
||||
```
|
||||
|
||||
Open browser to: `http://localhost:8000`
|
||||
|
||||
### Mapbox Token Setup
|
||||
|
||||
**IMPORTANT**: Before running, replace the placeholder token in `src/index.js`:
|
||||
|
||||
```javascript
|
||||
// Line 5 in src/index.js
|
||||
mapboxgl.accessToken = 'YOUR_ACTUAL_MAPBOX_TOKEN';
|
||||
```
|
||||
|
||||
Get a free token at: [https://account.mapbox.com/](https://account.mapbox.com/)
|
||||
|
||||
## Code Guidelines
|
||||
|
||||
### JavaScript Style
|
||||
- **ES6+ syntax**: Use modern JavaScript features
|
||||
- **Naming conventions**:
|
||||
- camelCase for variables and functions
|
||||
- PascalCase for classes
|
||||
- UPPER_CASE for constants
|
||||
- **Comments**: Explain "why" not "what"
|
||||
- **Async patterns**: Use async/await where appropriate
|
||||
|
||||
### Mapbox-Specific Notes
|
||||
|
||||
#### Globe Projection
|
||||
```javascript
|
||||
// Always specify projection for globe view
|
||||
const map = new mapboxgl.Map({
|
||||
projection: 'globe', // Required for 3D globe
|
||||
// ... other options
|
||||
});
|
||||
```
|
||||
|
||||
#### Coordinate Order
|
||||
GeoJSON uses `[longitude, latitude]` order (NOT lat/lng):
|
||||
```javascript
|
||||
"coordinates": [139.6917, 35.6895] // Tokyo: [lng, lat]
|
||||
```
|
||||
|
||||
#### Layer Management
|
||||
```javascript
|
||||
// Always check if source exists before adding layer
|
||||
if (!map.getSource('my-source')) {
|
||||
map.addSource('my-source', { /* ... */ });
|
||||
}
|
||||
|
||||
// Remove layers before sources
|
||||
if (map.getLayer('my-layer')) {
|
||||
map.removeLayer('my-layer');
|
||||
}
|
||||
if (map.getSource('my-source')) {
|
||||
map.removeSource('my-source');
|
||||
}
|
||||
```
|
||||
|
||||
#### Event Handling
|
||||
```javascript
|
||||
// Use 'load' event for initial setup
|
||||
map.on('load', () => {
|
||||
// Add sources and layers here
|
||||
});
|
||||
|
||||
// Use 'style.load' for style-dependent features
|
||||
map.on('style.load', () => {
|
||||
// Configure fog, terrain, etc.
|
||||
});
|
||||
```
|
||||
|
||||
### Data Patterns
|
||||
|
||||
#### GeoJSON Structure
|
||||
```javascript
|
||||
const data = {
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [lng, lat] // Note order!
|
||||
},
|
||||
"properties": {
|
||||
// Custom properties here
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
```
|
||||
|
||||
#### Expression Syntax
|
||||
```javascript
|
||||
// Interpolation for continuous values
|
||||
'circle-radius': [
|
||||
'interpolate',
|
||||
['linear'], // Interpolation type
|
||||
['get', 'value'], // Property to interpolate
|
||||
0, 5, // value: 0 -> radius: 5
|
||||
100, 20 // value: 100 -> radius: 20
|
||||
]
|
||||
|
||||
// Step function for discrete values
|
||||
'circle-color': [
|
||||
'step',
|
||||
['get', 'category'],
|
||||
'#blue', // default
|
||||
'A', '#red', // category A
|
||||
'B', '#green' // category B
|
||||
]
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
mapbox_globe_1/
|
||||
├── index.html # Main entry point
|
||||
│ ├── Mapbox GL JS CDN links
|
||||
│ ├── UI overlay elements (title, legend, info)
|
||||
│ └── Script imports
|
||||
│
|
||||
├── src/
|
||||
│ ├── index.js # Main application logic
|
||||
│ │ ├── Map initialization
|
||||
│ │ ├── Globe configuration (fog, projection)
|
||||
│ │ ├── Data layer setup
|
||||
│ │ ├── Interaction handlers
|
||||
│ │ └── Auto-rotation logic
|
||||
│ │
|
||||
│ └── data/
|
||||
│ └── population-data.js # GeoJSON data
|
||||
│ └── 100 city features with properties
|
||||
│
|
||||
├── README.md # User documentation
|
||||
└── CLAUDE.md # This file (dev guidelines)
|
||||
```
|
||||
|
||||
## Common Tasks
|
||||
|
||||
### Adding New Data Points
|
||||
Edit `src/data/population-data.js`:
|
||||
```javascript
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [lng, lat]
|
||||
},
|
||||
"properties": {
|
||||
"city": "City Name",
|
||||
"country": "Country",
|
||||
"population": 1000000,
|
||||
"year": 2024
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Modifying Visual Style
|
||||
|
||||
#### Change Circle Colors
|
||||
Edit `src/index.js`, find `circle-color` property:
|
||||
```javascript
|
||||
'circle-color': [
|
||||
'interpolate',
|
||||
['linear'],
|
||||
['get', 'population'],
|
||||
1000000, '#new-color-1',
|
||||
30000000, '#new-color-2'
|
||||
]
|
||||
```
|
||||
|
||||
#### Adjust Circle Sizes
|
||||
Edit `src/index.js`, find `circle-radius` property:
|
||||
```javascript
|
||||
'circle-radius': [
|
||||
'interpolate',
|
||||
['linear'],
|
||||
['get', 'population'],
|
||||
1000000, 6, // Increase from 4
|
||||
30000000, 30 // Increase from 24
|
||||
]
|
||||
```
|
||||
|
||||
#### Change Atmosphere
|
||||
Edit `src/index.js`, find `map.setFog()`:
|
||||
```javascript
|
||||
map.setFog({
|
||||
color: 'rgb(255, 255, 255)', // Lighter atmosphere
|
||||
'high-color': 'rgb(100, 150, 255)', // Different sky color
|
||||
'space-color': 'rgb(0, 0, 10)', // Darker space
|
||||
'star-intensity': 0.8 // More visible stars
|
||||
});
|
||||
```
|
||||
|
||||
### Customizing Rotation
|
||||
|
||||
#### Adjust Speed
|
||||
Edit `src/index.js`, find `startRotation()`:
|
||||
```javascript
|
||||
center.lng += 0.5; // Increase for faster rotation
|
||||
```
|
||||
|
||||
#### Change Duration
|
||||
```javascript
|
||||
map.easeTo({
|
||||
center: center,
|
||||
duration: 1000, // Decrease for faster, increase for slower
|
||||
easing: (t) => t
|
||||
});
|
||||
```
|
||||
|
||||
#### Disable Auto-Rotation
|
||||
Comment out in `src/index.js`:
|
||||
```javascript
|
||||
// startRotation(); // Disable this line
|
||||
```
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### For Large Datasets (500+ points)
|
||||
```javascript
|
||||
// Use clustering
|
||||
map.addSource('population', {
|
||||
type: 'geojson',
|
||||
data: populationData,
|
||||
cluster: true,
|
||||
clusterMaxZoom: 14,
|
||||
clusterRadius: 50
|
||||
});
|
||||
```
|
||||
|
||||
### For Mobile Devices
|
||||
```javascript
|
||||
// Reduce circle quality on mobile
|
||||
const isMobile = window.innerWidth < 768;
|
||||
'circle-radius': [
|
||||
'interpolate',
|
||||
['linear'],
|
||||
['get', 'population'],
|
||||
1000000, isMobile ? 3 : 4,
|
||||
30000000, isMobile ? 18 : 24
|
||||
]
|
||||
```
|
||||
|
||||
## Debugging Tips
|
||||
|
||||
### Check Map Load Status
|
||||
```javascript
|
||||
console.log('Map loaded:', map.loaded());
|
||||
console.log('Style loaded:', map.isStyleLoaded());
|
||||
```
|
||||
|
||||
### Inspect Layers and Sources
|
||||
```javascript
|
||||
console.log('Layers:', map.getStyle().layers);
|
||||
console.log('Sources:', Object.keys(map.getStyle().sources));
|
||||
```
|
||||
|
||||
### Monitor Events
|
||||
```javascript
|
||||
map.on('error', (e) => console.error('Map error:', e));
|
||||
map.on('dataloading', () => console.log('Data loading...'));
|
||||
map.on('idle', () => console.log('Map idle'));
|
||||
```
|
||||
|
||||
## API References
|
||||
|
||||
- [Mapbox GL JS API](https://docs.mapbox.com/mapbox-gl-js/api/)
|
||||
- [Mapbox Style Specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/)
|
||||
- [Mapbox Expressions](https://docs.mapbox.com/mapbox-gl-js/style-spec/expressions/)
|
||||
- [GeoJSON Specification](https://datatracker.ietf.org/doc/html/rfc7946)
|
||||
|
||||
## Version Information
|
||||
|
||||
- Mapbox GL JS: v3.0.1
|
||||
- GeoJSON: RFC 7946
|
||||
- Browser: Modern ES6+ support required
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Issue: Map not loading
|
||||
- Check Mapbox token is valid
|
||||
- Verify internet connection for CDN resources
|
||||
- Check browser console for errors
|
||||
|
||||
### Issue: Globe not appearing
|
||||
- Ensure `projection: 'globe'` is set
|
||||
- Check browser supports WebGL
|
||||
- Verify style has loaded (`map.isStyleLoaded()`)
|
||||
|
||||
### Issue: Circles not showing
|
||||
- Verify data is valid GeoJSON
|
||||
- Check coordinates are [lng, lat] order
|
||||
- Ensure layer is added after map loads
|
||||
|
||||
### Issue: Popups not appearing
|
||||
- Check feature properties exist
|
||||
- Verify layer ID matches event listener
|
||||
- Test with `map.queryRenderedFeatures()`
|
||||
|
||||
## Contributing Guidelines
|
||||
|
||||
When modifying this project:
|
||||
1. Test on multiple browsers
|
||||
2. Verify mobile responsiveness
|
||||
3. Update documentation
|
||||
4. Check console for errors
|
||||
5. Test with different data sizes
|
||||
6. Validate GeoJSON structure
|
||||
7. Ensure accessibility (ARIA labels, keyboard nav)
|
||||
|
||||
## Security Notes
|
||||
|
||||
- Never commit Mapbox tokens to version control
|
||||
- Use environment variables for production
|
||||
- Implement token rotation for public apps
|
||||
- Monitor token usage on Mapbox dashboard
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
# Globe Visualization 1: Global Population Distribution
|
||||
|
||||
An interactive 3D globe visualization showcasing the world's major urban centers using Mapbox GL JS. This project demonstrates fundamental globe projection techniques, atmospheric effects, and data-driven styling.
|
||||
|
||||
## Web Source
|
||||
|
||||
This visualization is based on techniques learned from:
|
||||
- **Primary Source**: [Mapbox Globe Example](https://docs.mapbox.com/mapbox-gl-js/example/globe/)
|
||||
- **API Documentation**: [Mapbox GL JS v3.0.1](https://docs.mapbox.com/mapbox-gl-js/api/)
|
||||
|
||||
## Techniques Learned
|
||||
|
||||
### 1. Globe Projection Setup
|
||||
- Initialized map with `projection: 'globe'` for 3D spherical view
|
||||
- Used `satellite-streets-v12` style optimized for globe visualization
|
||||
- Configured initial zoom and center for optimal viewing
|
||||
|
||||
### 2. Atmosphere & Fog Configuration
|
||||
- Implemented `map.setFog({})` for realistic atmospheric effects
|
||||
- Customized atmosphere colors: horizon, sky, and space
|
||||
- Added subtle star field for enhanced visual appeal
|
||||
|
||||
### 3. Data-Driven Styling
|
||||
- Used Mapbox expressions for dynamic circle sizing based on population
|
||||
- Implemented color interpolation for visual hierarchy
|
||||
- Applied stroke styling for better visibility
|
||||
|
||||
### 4. Interactivity
|
||||
- Auto-rotation with user interaction detection
|
||||
- Hover popups with detailed city information
|
||||
- Pause rotation on zoom or user interaction
|
||||
- Navigation and fullscreen controls
|
||||
|
||||
## How to Run
|
||||
|
||||
### Prerequisites
|
||||
1. Get a free Mapbox access token at [https://account.mapbox.com/](https://account.mapbox.com/)
|
||||
2. Replace the placeholder token in `src/index.js`:
|
||||
```javascript
|
||||
mapboxgl.accessToken = 'YOUR_ACTUAL_MAPBOX_TOKEN';
|
||||
```
|
||||
|
||||
### Local Server
|
||||
Run a local web server from this directory:
|
||||
|
||||
```bash
|
||||
# Using Python 3
|
||||
python -m http.server 8000
|
||||
|
||||
# Using Python 2
|
||||
python -m SimpleHTTPServer 8000
|
||||
|
||||
# Using Node.js http-server
|
||||
npx http-server -p 8000
|
||||
```
|
||||
|
||||
Then open your browser to: `http://localhost:8000`
|
||||
|
||||
## What It Demonstrates
|
||||
|
||||
### Visual Features
|
||||
- **3D Globe Projection**: Realistic spherical representation of Earth
|
||||
- **Population Visualization**: 100 major cities represented as scaled circles
|
||||
- **Color Encoding**: Population magnitude indicated by color intensity
|
||||
- **Atmospheric Effects**: Fog, horizon glow, and space rendering
|
||||
- **Auto-Rotation**: Gentle spinning animation with smart pause/resume
|
||||
|
||||
### Technical Features
|
||||
- **Data-Driven Styling**: Circle size and color based on population data
|
||||
- **Interactive Popups**: City details on hover
|
||||
- **Responsive Controls**: Navigation, zoom, and fullscreen
|
||||
- **Mobile Support**: Touch event handling
|
||||
- **Performance Optimization**: Efficient rendering of 100+ data points
|
||||
|
||||
### Data Coverage
|
||||
- **100 Cities** across all continents
|
||||
- **Population Range**: 1M to 40M people
|
||||
- **Geographic Diversity**: Cities from 50+ countries
|
||||
- **Data Year**: 2024 estimates
|
||||
|
||||
## Data Sources
|
||||
|
||||
Population data compiled from:
|
||||
- UN World Urbanization Prospects 2024
|
||||
- City government statistics
|
||||
- World Bank urban population data
|
||||
- National census reports
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
mapbox_globe_1/
|
||||
├── index.html # Main HTML with UI overlays
|
||||
├── src/
|
||||
│ ├── index.js # Globe initialization and interaction logic
|
||||
│ └── data/
|
||||
│ └── population-data.js # GeoJSON with city population data
|
||||
├── README.md # This file
|
||||
└── CLAUDE.md # Development guidelines
|
||||
```
|
||||
|
||||
## Key Code Patterns
|
||||
|
||||
### Globe Initialization
|
||||
```javascript
|
||||
const map = new mapboxgl.Map({
|
||||
container: 'map',
|
||||
style: 'mapbox://styles/mapbox/satellite-streets-v12',
|
||||
projection: 'globe',
|
||||
zoom: 1.5,
|
||||
center: [30, 20]
|
||||
});
|
||||
```
|
||||
|
||||
### Atmosphere Setup
|
||||
```javascript
|
||||
map.setFog({
|
||||
color: 'rgb(186, 210, 235)',
|
||||
'high-color': 'rgb(36, 92, 223)',
|
||||
'horizon-blend': 0.02,
|
||||
'space-color': 'rgb(11, 11, 25)',
|
||||
'star-intensity': 0.6
|
||||
});
|
||||
```
|
||||
|
||||
### Data-Driven Styling
|
||||
```javascript
|
||||
'circle-radius': [
|
||||
'interpolate',
|
||||
['linear'],
|
||||
['get', 'population'],
|
||||
1000000, 4,
|
||||
30000000, 24
|
||||
]
|
||||
```
|
||||
|
||||
## Browser Compatibility
|
||||
|
||||
- Chrome/Edge: Full support
|
||||
- Firefox: Full support
|
||||
- Safari: Full support (v15.4+)
|
||||
- Mobile browsers: Full support with touch controls
|
||||
|
||||
## Performance Notes
|
||||
|
||||
- Optimized for 100-200 data points
|
||||
- Globe projection may be GPU intensive on older devices
|
||||
- Auto-rotation pauses automatically when needed
|
||||
- Efficient event handling for smooth interaction
|
||||
|
||||
## Next Steps
|
||||
|
||||
This is the first in a series of globe visualizations. Future iterations will explore:
|
||||
- Animated data flows between cities
|
||||
- Time-series population changes
|
||||
- 3D extruded buildings
|
||||
- Custom globe textures
|
||||
- Advanced camera animations
|
||||
- Real-time data integration
|
||||
|
||||
## License
|
||||
|
||||
This is an educational example. Please review Mapbox's terms of service for production use.
|
||||
|
|
@ -0,0 +1,175 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Globe Viz 1: Global Population Distribution</title>
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/v3.0.1/mapbox-gl.css" rel="stylesheet">
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/v3.0.1/mapbox-gl.js"></script>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
}
|
||||
|
||||
#map {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.title-overlay {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
left: 20px;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
color: #ffffff;
|
||||
padding: 15px 20px;
|
||||
border-radius: 8px;
|
||||
z-index: 1;
|
||||
max-width: 350px;
|
||||
}
|
||||
|
||||
.title-overlay h1 {
|
||||
margin: 0 0 8px 0;
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.title-overlay p {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
color: #cccccc;
|
||||
}
|
||||
|
||||
.legend {
|
||||
position: absolute;
|
||||
bottom: 30px;
|
||||
right: 20px;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
color: #ffffff;
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.legend h3 {
|
||||
margin: 0 0 10px 0;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.legend-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 8px 0;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.legend-circle {
|
||||
border-radius: 50%;
|
||||
margin-right: 10px;
|
||||
background: rgba(255, 99, 71, 0.8);
|
||||
}
|
||||
|
||||
.info-panel {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
color: #ffffff;
|
||||
padding: 12px 15px;
|
||||
border-radius: 8px;
|
||||
z-index: 1;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.info-panel .label {
|
||||
color: #888888;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.info-panel .value {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #ff6347;
|
||||
}
|
||||
|
||||
.mapboxgl-popup-content {
|
||||
background: rgba(0, 0, 0, 0.9);
|
||||
color: #ffffff;
|
||||
padding: 12px 15px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.mapboxgl-popup-content h3 {
|
||||
margin: 0 0 8px 0;
|
||||
font-size: 16px;
|
||||
color: #ff6347;
|
||||
}
|
||||
|
||||
.mapboxgl-popup-content p {
|
||||
margin: 4px 0;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.mapboxgl-popup-tip {
|
||||
border-top-color: rgba(0, 0, 0, 0.9) !important;
|
||||
}
|
||||
|
||||
.mapboxgl-ctrl-group {
|
||||
background: rgba(0, 0, 0, 0.8) !important;
|
||||
}
|
||||
|
||||
.mapboxgl-ctrl-group button {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
.mapboxgl-ctrl-group button:hover {
|
||||
background-color: rgba(255, 255, 255, 0.1) !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="map"></div>
|
||||
|
||||
<div class="title-overlay">
|
||||
<h1>Global Population Distribution</h1>
|
||||
<p>Visualizing the world's major urban centers on an interactive 3D globe</p>
|
||||
</div>
|
||||
|
||||
<div class="info-panel">
|
||||
<div class="label">Total Cities</div>
|
||||
<div class="value" id="city-count">Loading...</div>
|
||||
</div>
|
||||
|
||||
<div class="legend">
|
||||
<h3>Population Size</h3>
|
||||
<div class="legend-item">
|
||||
<div class="legend-circle" style="width: 24px; height: 24px;"></div>
|
||||
<span>30M+ people</span>
|
||||
</div>
|
||||
<div class="legend-item">
|
||||
<div class="legend-circle" style="width: 18px; height: 18px;"></div>
|
||||
<span>20M - 30M</span>
|
||||
</div>
|
||||
<div class="legend-item">
|
||||
<div class="legend-circle" style="width: 14px; height: 14px;"></div>
|
||||
<span>10M - 20M</span>
|
||||
</div>
|
||||
<div class="legend-item">
|
||||
<div class="legend-circle" style="width: 10px; height: 10px;"></div>
|
||||
<span>5M - 10M</span>
|
||||
</div>
|
||||
<div class="legend-item">
|
||||
<div class="legend-circle" style="width: 6px; height: 6px;"></div>
|
||||
<span>1M - 5M</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="src/data/population-data.js"></script>
|
||||
<script type="module" src="src/index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,499 @@
|
|||
// Global Population Data - Major Cities Worldwide (2024)
|
||||
// Data sourced from UN World Urbanization Prospects and city statistics
|
||||
|
||||
const populationData = {
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
// Asia - East
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [139.6917, 35.6895] },
|
||||
"properties": { "city": "Tokyo", "country": "Japan", "population": 37400000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [121.4737, 31.2304] },
|
||||
"properties": { "city": "Shanghai", "country": "China", "population": 27800000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [116.4074, 39.9042] },
|
||||
"properties": { "city": "Beijing", "country": "China", "population": 21500000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [126.9780, 37.5665] },
|
||||
"properties": { "city": "Seoul", "country": "South Korea", "population": 25600000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [113.2644, 23.1291] },
|
||||
"properties": { "city": "Guangzhou", "country": "China", "population": 13500000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [114.1095, 22.3964] },
|
||||
"properties": { "city": "Shenzhen", "country": "China", "population": 13400000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [135.5023, 34.6937] },
|
||||
"properties": { "city": "Osaka", "country": "Japan", "population": 19300000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [114.1694, 22.3193] },
|
||||
"properties": { "city": "Hong Kong", "country": "China", "population": 7500000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [120.9842, 14.5995] },
|
||||
"properties": { "city": "Manila", "country": "Philippines", "population": 14000000, "year": 2024 }
|
||||
},
|
||||
|
||||
// Asia - South
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [72.8777, 19.0760] },
|
||||
"properties": { "city": "Mumbai", "country": "India", "population": 21000000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [77.1025, 28.7041] },
|
||||
"properties": { "city": "Delhi", "country": "India", "population": 32900000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [77.5946, 12.9716] },
|
||||
"properties": { "city": "Bangalore", "country": "India", "population": 12800000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [88.3639, 22.5726] },
|
||||
"properties": { "city": "Kolkata", "country": "India", "population": 15000000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [80.2707, 13.0827] },
|
||||
"properties": { "city": "Chennai", "country": "India", "population": 11000000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [78.4867, 17.3850] },
|
||||
"properties": { "city": "Hyderabad", "country": "India", "population": 10500000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [67.0099, 24.8607] },
|
||||
"properties": { "city": "Karachi", "country": "Pakistan", "population": 16800000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [73.0479, 33.6844] },
|
||||
"properties": { "city": "Islamabad", "country": "Pakistan", "population": 2200000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [74.3436, 31.5497] },
|
||||
"properties": { "city": "Lahore", "country": "Pakistan", "population": 13000000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [90.4125, 23.8103] },
|
||||
"properties": { "city": "Dhaka", "country": "Bangladesh", "population": 22400000, "year": 2024 }
|
||||
},
|
||||
|
||||
// Asia - Southeast
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [106.8456, -6.2088] },
|
||||
"properties": { "city": "Jakarta", "country": "Indonesia", "population": 34500000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [100.5018, 13.7563] },
|
||||
"properties": { "city": "Bangkok", "country": "Thailand", "population": 11000000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [103.8198, 1.3521] },
|
||||
"properties": { "city": "Singapore", "country": "Singapore", "population": 5900000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [101.6869, 3.1390] },
|
||||
"properties": { "city": "Kuala Lumpur", "country": "Malaysia", "population": 8600000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [106.8650, -6.1751] },
|
||||
"properties": { "city": "Bandung", "country": "Indonesia", "population": 7800000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [105.8342, 21.0285] },
|
||||
"properties": { "city": "Hanoi", "country": "Vietnam", "population": 8400000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [106.6297, 10.8231] },
|
||||
"properties": { "city": "Ho Chi Minh City", "country": "Vietnam", "population": 9000000, "year": 2024 }
|
||||
},
|
||||
|
||||
// Middle East
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [51.5074, 25.2854] },
|
||||
"properties": { "city": "Doha", "country": "Qatar", "population": 2400000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [55.2708, 25.2048] },
|
||||
"properties": { "city": "Dubai", "country": "UAE", "population": 3500000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [51.4215, 35.6892] },
|
||||
"properties": { "city": "Tehran", "country": "Iran", "population": 9500000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [44.3661, 33.3152] },
|
||||
"properties": { "city": "Baghdad", "country": "Iraq", "population": 7700000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [46.7219, 24.7136] },
|
||||
"properties": { "city": "Riyadh", "country": "Saudi Arabia", "population": 7600000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [35.2433, 31.9454] },
|
||||
"properties": { "city": "Amman", "country": "Jordan", "population": 4200000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [35.4951, 33.8938] },
|
||||
"properties": { "city": "Beirut", "country": "Lebanon", "population": 2400000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [35.2137, 31.7683] },
|
||||
"properties": { "city": "Jerusalem", "country": "Israel", "population": 1400000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [34.7818, 32.0853] },
|
||||
"properties": { "city": "Tel Aviv", "country": "Israel", "population": 4300000, "year": 2024 }
|
||||
},
|
||||
|
||||
// Europe - West
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [-0.1278, 51.5074] },
|
||||
"properties": { "city": "London", "country": "United Kingdom", "population": 9600000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [2.3522, 48.8566] },
|
||||
"properties": { "city": "Paris", "country": "France", "population": 11000000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [13.4050, 52.5200] },
|
||||
"properties": { "city": "Berlin", "country": "Germany", "population": 3800000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [-3.7038, 40.4168] },
|
||||
"properties": { "city": "Madrid", "country": "Spain", "population": 6700000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [2.1734, 41.3851] },
|
||||
"properties": { "city": "Barcelona", "country": "Spain", "population": 5600000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [12.4964, 41.9028] },
|
||||
"properties": { "city": "Rome", "country": "Italy", "population": 4300000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [9.1900, 45.4642] },
|
||||
"properties": { "city": "Milan", "country": "Italy", "population": 3200000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [4.9041, 52.3676] },
|
||||
"properties": { "city": "Amsterdam", "country": "Netherlands", "population": 2400000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [4.3517, 50.8503] },
|
||||
"properties": { "city": "Brussels", "country": "Belgium", "population": 2100000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [8.6821, 50.1109] },
|
||||
"properties": { "city": "Frankfurt", "country": "Germany", "population": 2900000, "year": 2024 }
|
||||
},
|
||||
|
||||
// Europe - East
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [37.6173, 55.7558] },
|
||||
"properties": { "city": "Moscow", "country": "Russia", "population": 12600000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [30.5234, 50.4501] },
|
||||
"properties": { "city": "Kyiv", "country": "Ukraine", "population": 2900000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [21.0122, 52.2297] },
|
||||
"properties": { "city": "Warsaw", "country": "Poland", "population": 3100000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [19.0402, 47.4979] },
|
||||
"properties": { "city": "Budapest", "country": "Hungary", "population": 3000000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [23.3219, 42.6977] },
|
||||
"properties": { "city": "Sofia", "country": "Bulgaria", "population": 1200000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [26.1025, 44.4268] },
|
||||
"properties": { "city": "Bucharest", "country": "Romania", "population": 2100000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [14.4378, 50.0755] },
|
||||
"properties": { "city": "Prague", "country": "Czech Republic", "population": 1300000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [30.3141, 59.9343] },
|
||||
"properties": { "city": "Saint Petersburg", "country": "Russia", "population": 5400000, "year": 2024 }
|
||||
},
|
||||
|
||||
// Africa - North
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [31.2357, 30.0444] },
|
||||
"properties": { "city": "Cairo", "country": "Egypt", "population": 21800000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [-6.8498, 34.0209] },
|
||||
"properties": { "city": "Rabat", "country": "Morocco", "population": 1900000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [3.0588, 36.7538] },
|
||||
"properties": { "city": "Algiers", "country": "Algeria", "population": 2800000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [10.1815, 36.8065] },
|
||||
"properties": { "city": "Tunis", "country": "Tunisia", "population": 2400000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [13.1913, 32.8872] },
|
||||
"properties": { "city": "Tripoli", "country": "Libya", "population": 1200000, "year": 2024 }
|
||||
},
|
||||
|
||||
// Africa - Sub-Saharan
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [3.3792, 6.5244] },
|
||||
"properties": { "city": "Lagos", "country": "Nigeria", "population": 15400000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [7.4914, 9.0579] },
|
||||
"properties": { "city": "Abuja", "country": "Nigeria", "population": 3500000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [36.8219, -1.2921] },
|
||||
"properties": { "city": "Nairobi", "country": "Kenya", "population": 5100000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [28.0473, -26.2041] },
|
||||
"properties": { "city": "Johannesburg", "country": "South Africa", "population": 6100000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [18.4241, -33.9249] },
|
||||
"properties": { "city": "Cape Town", "country": "South Africa", "population": 4700000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [15.2663, -4.3276] },
|
||||
"properties": { "city": "Kinshasa", "country": "DR Congo", "population": 16300000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [32.6297, -25.9655] },
|
||||
"properties": { "city": "Maputo", "country": "Mozambique", "population": 1100000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [32.5825, 15.5007] },
|
||||
"properties": { "city": "Khartoum", "country": "Sudan", "population": 6100000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [38.7469, 9.0054] },
|
||||
"properties": { "city": "Addis Ababa", "country": "Ethiopia", "population": 5200000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [-1.6163, 6.6745] },
|
||||
"properties": { "city": "Accra", "country": "Ghana", "population": 2500000, "year": 2024 }
|
||||
},
|
||||
|
||||
// North America
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [-99.1332, 19.4326] },
|
||||
"properties": { "city": "Mexico City", "country": "Mexico", "population": 22100000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [-74.0060, 40.7128] },
|
||||
"properties": { "city": "New York", "country": "USA", "population": 18900000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [-118.2437, 34.0522] },
|
||||
"properties": { "city": "Los Angeles", "country": "USA", "population": 12500000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [-87.6298, 41.8781] },
|
||||
"properties": { "city": "Chicago", "country": "USA", "population": 8900000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [-95.3698, 29.7604] },
|
||||
"properties": { "city": "Houston", "country": "USA", "population": 6400000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [-112.0740, 33.4484] },
|
||||
"properties": { "city": "Phoenix", "country": "USA", "population": 4900000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [-75.1652, 39.9526] },
|
||||
"properties": { "city": "Philadelphia", "country": "USA", "population": 5700000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [-79.3832, 43.6532] },
|
||||
"properties": { "city": "Toronto", "country": "Canada", "population": 6400000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [-123.1207, 49.2827] },
|
||||
"properties": { "city": "Vancouver", "country": "Canada", "population": 2600000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [-75.6972, 45.4215] },
|
||||
"properties": { "city": "Ottawa", "country": "Canada", "population": 1400000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [-100.3161, 25.6866] },
|
||||
"properties": { "city": "Monterrey", "country": "Mexico", "population": 5300000, "year": 2024 }
|
||||
},
|
||||
|
||||
// South America
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [-46.6333, -23.5505] },
|
||||
"properties": { "city": "São Paulo", "country": "Brazil", "population": 22600000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [-43.1729, -22.9068] },
|
||||
"properties": { "city": "Rio de Janeiro", "country": "Brazil", "population": 13700000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [-58.3816, -34.6037] },
|
||||
"properties": { "city": "Buenos Aires", "country": "Argentina", "population": 15400000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [-77.0428, -12.0464] },
|
||||
"properties": { "city": "Lima", "country": "Peru", "population": 11200000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [-74.0721, 4.7110] },
|
||||
"properties": { "city": "Bogotá", "country": "Colombia", "population": 11300000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [-70.6693, -33.4489] },
|
||||
"properties": { "city": "Santiago", "country": "Chile", "population": 6800000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [-47.8825, -15.7942] },
|
||||
"properties": { "city": "Brasília", "country": "Brazil", "population": 4700000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [-78.4678, -0.1807] },
|
||||
"properties": { "city": "Quito", "country": "Ecuador", "population": 2900000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [-56.1645, -34.9011] },
|
||||
"properties": { "city": "Montevideo", "country": "Uruguay", "population": 1800000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [-57.5759, -25.2637] },
|
||||
"properties": { "city": "Asunción", "country": "Paraguay", "population": 3300000, "year": 2024 }
|
||||
},
|
||||
|
||||
// Oceania
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [151.2093, -33.8688] },
|
||||
"properties": { "city": "Sydney", "country": "Australia", "population": 5400000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [144.9631, -37.8136] },
|
||||
"properties": { "city": "Melbourne", "country": "Australia", "population": 5200000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [174.7633, -36.8485] },
|
||||
"properties": { "city": "Auckland", "country": "New Zealand", "population": 1700000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [153.0251, -27.4698] },
|
||||
"properties": { "city": "Brisbane", "country": "Australia", "population": 2600000, "year": 2024 }
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [115.8605, -31.9505] },
|
||||
"properties": { "city": "Perth", "country": "Australia", "population": 2200000, "year": 2024 }
|
||||
}
|
||||
]
|
||||
};
|
||||
|
|
@ -0,0 +1,181 @@
|
|||
// Mapbox Globe Visualization - Global Population Distribution
|
||||
// Demonstrates: Globe projection, fog/atmosphere, data-driven styling, interactive popups
|
||||
|
||||
// Note: Replace with your own Mapbox access token
|
||||
// Get a free token at https://account.mapbox.com/
|
||||
mapboxgl.accessToken = 'pk.eyJ1IjoiZXhhbXBsZSIsImEiOiJjbGV4YW1wbGUifQ.example_token_replace_with_yours';
|
||||
|
||||
// Initialize map with globe projection
|
||||
const map = new mapboxgl.Map({
|
||||
container: 'map',
|
||||
// Use satellite style for optimal globe visualization
|
||||
style: 'mapbox://styles/mapbox/satellite-streets-v12',
|
||||
projection: 'globe', // Enable 3D globe projection
|
||||
zoom: 1.5,
|
||||
center: [30, 20], // Center on Africa/Europe
|
||||
pitch: 0
|
||||
});
|
||||
|
||||
// Track rotation state
|
||||
let isRotating = true;
|
||||
let userInteracted = false;
|
||||
|
||||
// Add navigation controls and fullscreen
|
||||
map.addControl(new mapboxgl.NavigationControl(), 'top-left');
|
||||
map.addControl(new mapboxgl.FullscreenControl(), 'top-left');
|
||||
|
||||
// Configure atmosphere and fog for realistic globe appearance
|
||||
map.on('style.load', () => {
|
||||
// Enable fog/atmosphere with default settings for realistic globe effect
|
||||
map.setFog({
|
||||
color: 'rgb(186, 210, 235)', // Light blue atmosphere
|
||||
'high-color': 'rgb(36, 92, 223)', // Upper atmosphere color
|
||||
'horizon-blend': 0.02, // Smooth transition at horizon
|
||||
'space-color': 'rgb(11, 11, 25)', // Dark space color
|
||||
'star-intensity': 0.6 // Subtle star field
|
||||
});
|
||||
});
|
||||
|
||||
// Add population data layer when map loads
|
||||
map.on('load', () => {
|
||||
// Add the population data source
|
||||
map.addSource('population', {
|
||||
type: 'geojson',
|
||||
data: populationData
|
||||
});
|
||||
|
||||
// Add circle layer with data-driven styling
|
||||
map.addLayer({
|
||||
id: 'population-circles',
|
||||
type: 'circle',
|
||||
source: 'population',
|
||||
paint: {
|
||||
// Size circles based on population using interpolation
|
||||
'circle-radius': [
|
||||
'interpolate',
|
||||
['linear'],
|
||||
['get', 'population'],
|
||||
1000000, 4, // 1M people = 4px radius
|
||||
5000000, 8, // 5M people = 8px radius
|
||||
10000000, 12, // 10M people = 12px radius
|
||||
20000000, 18, // 20M people = 18px radius
|
||||
30000000, 24 // 30M+ people = 24px radius
|
||||
],
|
||||
// Color based on population density
|
||||
'circle-color': [
|
||||
'interpolate',
|
||||
['linear'],
|
||||
['get', 'population'],
|
||||
1000000, '#FFA500', // Orange for smaller cities
|
||||
10000000, '#FF6347', // Tomato for medium cities
|
||||
20000000, '#FF4500', // Orange-red for large cities
|
||||
30000000, '#DC143C' // Crimson for mega-cities
|
||||
],
|
||||
'circle-opacity': 0.85,
|
||||
'circle-stroke-width': 1,
|
||||
'circle-stroke-color': '#ffffff',
|
||||
'circle-stroke-opacity': 0.6
|
||||
}
|
||||
});
|
||||
|
||||
// Update city count
|
||||
const cityCount = populationData.features.length;
|
||||
document.getElementById('city-count').textContent = cityCount;
|
||||
|
||||
// Add popup on hover
|
||||
const popup = new mapboxgl.Popup({
|
||||
closeButton: false,
|
||||
closeOnClick: false,
|
||||
offset: 10
|
||||
});
|
||||
|
||||
map.on('mouseenter', 'population-circles', (e) => {
|
||||
map.getCanvas().style.cursor = 'pointer';
|
||||
|
||||
const coordinates = e.features[0].geometry.coordinates.slice();
|
||||
const props = e.features[0].properties;
|
||||
|
||||
// Format population with commas
|
||||
const formattedPop = props.population.toLocaleString();
|
||||
|
||||
const html = `
|
||||
<h3>${props.city}</h3>
|
||||
<p><strong>${props.country}</strong></p>
|
||||
<p>Population: ${formattedPop}</p>
|
||||
<p>Year: ${props.year}</p>
|
||||
`;
|
||||
|
||||
popup.setLngLat(coordinates)
|
||||
.setHTML(html)
|
||||
.addTo(map);
|
||||
});
|
||||
|
||||
map.on('mouseleave', 'population-circles', () => {
|
||||
map.getCanvas().style.cursor = '';
|
||||
popup.remove();
|
||||
});
|
||||
|
||||
// Start gentle auto-rotation
|
||||
startRotation();
|
||||
});
|
||||
|
||||
// Rotation function for gentle globe spinning
|
||||
function startRotation() {
|
||||
if (!isRotating || userInteracted) return;
|
||||
|
||||
// Rotate the globe slowly
|
||||
const center = map.getCenter();
|
||||
center.lng += 0.5; // Adjust speed here (degrees per frame)
|
||||
|
||||
map.easeTo({
|
||||
center: center,
|
||||
duration: 1000,
|
||||
easing: (t) => t // Linear easing for smooth rotation
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
requestAnimationFrame(startRotation);
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
// Pause rotation on user interaction
|
||||
map.on('mousedown', () => {
|
||||
userInteracted = true;
|
||||
isRotating = false;
|
||||
});
|
||||
|
||||
// Resume rotation after inactivity
|
||||
let inactivityTimer;
|
||||
map.on('mouseup', () => {
|
||||
clearTimeout(inactivityTimer);
|
||||
inactivityTimer = setTimeout(() => {
|
||||
if (map.getZoom() < 3) { // Only rotate at globe zoom levels
|
||||
userInteracted = false;
|
||||
isRotating = true;
|
||||
startRotation();
|
||||
}
|
||||
}, 3000); // Resume after 3 seconds of inactivity
|
||||
});
|
||||
|
||||
// Pause rotation when zoomed in
|
||||
map.on('zoom', () => {
|
||||
if (map.getZoom() >= 3) {
|
||||
isRotating = false;
|
||||
} else if (!userInteracted) {
|
||||
isRotating = true;
|
||||
}
|
||||
});
|
||||
|
||||
// Handle touch events for mobile
|
||||
map.on('touchstart', () => {
|
||||
userInteracted = true;
|
||||
isRotating = false;
|
||||
});
|
||||
|
||||
// Log when map is ready
|
||||
map.on('idle', () => {
|
||||
if (map.loaded()) {
|
||||
console.log('Globe visualization loaded successfully');
|
||||
console.log(`Displaying ${populationData.features.length} cities`);
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,470 @@
|
|||
# Mapbox 3D Globe Visualization - Progressive Web-Enhanced Specification
|
||||
|
||||
## Core Challenge
|
||||
Create progressively sophisticated Mapbox GL JS 3D globe visualizations that improve with each iteration by integrating knowledge from Mapbox documentation, tutorials, and examples. Each iteration should represent a measurable improvement in visual design, interactivity, data handling, or technical implementation using the globe projection feature.
|
||||
|
||||
## Output Requirements
|
||||
|
||||
**Directory Naming**: `mapbox_globe_[iteration_number]/`
|
||||
|
||||
**Content Structure**: Multi-file Mapbox application
|
||||
```
|
||||
mapbox_globe_[iteration_number]/
|
||||
├── index.html # Main HTML with Mapbox GL JS setup
|
||||
├── src/
|
||||
│ ├── index.js # Core visualization logic
|
||||
│ └── data/
|
||||
│ └── data.js # Embedded GeoJSON or data
|
||||
├── README.md # Documentation of iteration
|
||||
└── CLAUDE.md # Project guidelines
|
||||
```
|
||||
|
||||
### index.html Template
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Globe Viz [N]: [Descriptive Title]</title>
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/v3.0.1/mapbox-gl.css" rel="stylesheet">
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/v3.0.1/mapbox-gl.js"></script>
|
||||
<style>
|
||||
/* Globe-specific styling */
|
||||
/* Overlays, legends, controls */
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="map"></div>
|
||||
<!-- Overlays: title, legend, info panel -->
|
||||
<script src="src/data/data.js"></script>
|
||||
<script type="module" src="src/index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
### src/index.js Template
|
||||
```js
|
||||
// Mapbox access token (use public example token or placeholder)
|
||||
mapboxgl.accessToken = 'pk.example...';
|
||||
|
||||
// Initialize map with globe projection
|
||||
const map = new mapboxgl.Map({
|
||||
container: 'map',
|
||||
style: 'mapbox://styles/mapbox/[style]',
|
||||
projection: 'globe',
|
||||
center: [lng, lat],
|
||||
zoom: 1.5
|
||||
});
|
||||
|
||||
map.on('load', () => {
|
||||
// Configure globe atmosphere
|
||||
map.setFog({...});
|
||||
|
||||
// Add data source
|
||||
map.addSource('data-source', {...});
|
||||
|
||||
// Add visualization layers
|
||||
map.addLayer({...});
|
||||
|
||||
// Add interactions
|
||||
// Popups, filters, animations
|
||||
});
|
||||
|
||||
// Add controls
|
||||
map.addControl(new mapboxgl.NavigationControl());
|
||||
```
|
||||
|
||||
## Progressive Enhancement Dimensions
|
||||
|
||||
### **Visual Complexity Evolution**
|
||||
- **Iteration 1-3**: Single layer visualizations (heatmap OR points OR choropleth)
|
||||
- **Iteration 4-6**: Multi-layer compositions (heatmap + points, choropleth + labels)
|
||||
- **Iteration 7-10**: Advanced features (3D extrusions, custom markers, animations)
|
||||
- **Iteration 11+**: Innovative techniques (custom shaders, WebGL layers, data-driven styling)
|
||||
|
||||
### **Data Handling Sophistication**
|
||||
- **Basic**: Static GeoJSON with <100 features, simple properties
|
||||
- **Intermediate**: Multiple data sources, 100-1000 features, property-based styling
|
||||
- **Advanced**: Dynamic data loading, large datasets (1000+ features), spatial queries
|
||||
- **Expert**: Real-time data, vector tiles, spatial analysis, clustering
|
||||
|
||||
### **Interactivity Progression**
|
||||
- **Basic**: Hover popups, basic zoom/pan
|
||||
- **Intermediate**: Click events, filtering, layer toggling, search
|
||||
- **Advanced**: Timeline scrubbing, multi-view coordination, custom controls
|
||||
- **Expert**: Data-driven animations, user data input, export capabilities
|
||||
|
||||
### **Technical Implementation**
|
||||
- **Foundation**: Basic globe setup, single data source, simple layer
|
||||
- **Intermediate**: Multiple layers, Mapbox expressions, custom styling
|
||||
- **Advanced**: 3D features, custom projections, performance optimization
|
||||
- **Expert**: Custom sources, WebGL integration, advanced expressions
|
||||
|
||||
## Web Research Integration Strategy
|
||||
|
||||
### **Initial Priming Phase URLs**
|
||||
The priming agent should research these foundational topics:
|
||||
1. Mapbox GL JS overview and globe projection
|
||||
2. GeoJSON format and data structures
|
||||
3. Mapbox expression syntax fundamentals
|
||||
4. Layer types and their use cases
|
||||
5. Performance best practices
|
||||
|
||||
### **Iteration URL Strategy**
|
||||
|
||||
**URL Categories for Progressive Learning:**
|
||||
|
||||
1. **Foundation URLs (Iterations 1-5)**
|
||||
- Mapbox GL JS getting started guide
|
||||
- Globe projection documentation
|
||||
- Basic layer types (circle, heatmap, fill)
|
||||
- GeoJSON data format
|
||||
- Simple popup and interaction patterns
|
||||
|
||||
2. **Intermediate URLs (Iterations 6-12)**
|
||||
- Advanced layer styling with expressions
|
||||
- Multiple data sources and layers
|
||||
- Custom controls and UI elements
|
||||
- Data-driven styling techniques
|
||||
- Filter and query features
|
||||
- Color ramps and visual variables
|
||||
|
||||
3. **Advanced URLs (Iterations 13-20)**
|
||||
- 3D extrusions and fill-extrusion layers
|
||||
- Custom markers and symbols
|
||||
- Animation techniques (flyTo, easeTo, camera animations)
|
||||
- Vector tiles integration
|
||||
- Spatial queries and analysis
|
||||
- Performance optimization for large datasets
|
||||
|
||||
4. **Expert URLs (Iterations 21+)**
|
||||
- Custom WebGL layers
|
||||
- Advanced projections
|
||||
- Real-time data integration
|
||||
- Custom shaders and rendering
|
||||
- Complex spatial analysis
|
||||
- Multi-map coordination
|
||||
|
||||
### **Dynamic URL Discovery**
|
||||
Each iteration can also perform targeted web searches:
|
||||
- "Mapbox GL JS [specific technique] example"
|
||||
- "Mapbox globe [feature] tutorial"
|
||||
- "Mapbox expressions [use case]"
|
||||
- "Mapbox performance optimization [context]"
|
||||
|
||||
## Visualization Themes to Explore
|
||||
|
||||
### **Economic & Development**
|
||||
- Global GDP, income distribution, trade flows
|
||||
- Economic indicators, development indices
|
||||
- Stock market data, cryptocurrency adoption
|
||||
- Tourism, remittances, foreign investment
|
||||
|
||||
### **Environmental & Climate**
|
||||
- Temperature anomalies, climate zones
|
||||
- Deforestation, biodiversity hotspots
|
||||
- Carbon emissions, renewable energy adoption
|
||||
- Ocean currents, air quality, pollution
|
||||
|
||||
### **Demographic & Social**
|
||||
- Population density, urbanization
|
||||
- Life expectancy, health indicators
|
||||
- Education levels, literacy rates
|
||||
- Migration patterns, refugee flows
|
||||
|
||||
### **Infrastructure & Technology**
|
||||
- Internet penetration, mobile usage
|
||||
- Transportation networks, airports
|
||||
- Renewable energy installations
|
||||
- Satellite coverage, telecommunications
|
||||
|
||||
### **Political & Historical**
|
||||
- Election results, democracy indices
|
||||
- Conflict zones, peace agreements
|
||||
- Colonial history, independence dates
|
||||
- Language families, cultural regions
|
||||
|
||||
### **Natural Phenomena**
|
||||
- Earthquake activity, volcanic zones
|
||||
- Hurricane/typhoon tracks
|
||||
- Meteor impact sites
|
||||
- Magnetic field variations
|
||||
|
||||
## Data Format Requirements
|
||||
|
||||
### **GeoJSON Structure**
|
||||
```javascript
|
||||
const data = {
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Point", // or Polygon, LineString
|
||||
"coordinates": [longitude, latitude]
|
||||
},
|
||||
"properties": {
|
||||
"name": "Country/Region Name",
|
||||
"value": 12345,
|
||||
"category": "Type",
|
||||
"year": 2024,
|
||||
// Additional properties for styling/popups
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
```
|
||||
|
||||
### **Data Quality Standards**
|
||||
- Accurate geographic coordinates (longitude, latitude order)
|
||||
- Meaningful property names
|
||||
- Realistic values appropriate to theme
|
||||
- 50-500 features for most visualizations
|
||||
- Include metadata (year, source, data type)
|
||||
|
||||
## Quality Standards
|
||||
|
||||
### **Code Quality**
|
||||
- **Mapbox Best Practices**: Proper layer ordering, efficient expressions, appropriate layer types
|
||||
- **Performance**: Smooth 60fps rotation, efficient rendering for large datasets
|
||||
- **Accessibility**: Keyboard navigation, screen reader support where applicable
|
||||
- **Responsive**: Works on desktop and mobile with appropriate touch controls
|
||||
- **Clean Code**: Well-organized, commented, maintainable JavaScript
|
||||
|
||||
### **Visual Excellence**
|
||||
- **Clarity**: Data patterns immediately apparent on the globe
|
||||
- **Aesthetics**: Professional color schemes, appropriate visual hierarchy
|
||||
- **Globe Features**: Proper atmosphere, stars, fog effects
|
||||
- **Innovation**: Creative visualization approaches for data
|
||||
- **Usability**: Intuitive controls, clear legends, informative popups
|
||||
|
||||
### **Web Integration Quality**
|
||||
- **Source Attribution**: Each iteration credits the web source
|
||||
- **Knowledge Application**: Demonstrates specific Mapbox technique learned
|
||||
- **Progressive Learning**: Shows clear improvement over previous iteration
|
||||
- **Novel Synthesis**: Combines multiple web sources creatively
|
||||
|
||||
## Iteration Evolution Pattern
|
||||
|
||||
### **Knowledge Accumulation Strategy**
|
||||
|
||||
**Wave 1 (Iterations 1-5): Foundation Building**
|
||||
- Master basic globe setup and projection
|
||||
- Learn fundamental layer types (circle, heatmap, fill)
|
||||
- Establish data handling and GeoJSON patterns
|
||||
- Focus: Technical competence with globe basics
|
||||
|
||||
**Wave 2 (Iterations 6-12): Enhancement & Styling**
|
||||
- Advanced expression syntax
|
||||
- Multi-layer compositions
|
||||
- Interactive controls and filtering
|
||||
- Focus: Visual sophistication and user experience
|
||||
|
||||
**Wave 3 (Iterations 13-20): Advanced Features**
|
||||
- 3D extrusions and depth
|
||||
- Custom markers and symbols
|
||||
- Animation and camera control
|
||||
- Focus: Technical excellence and innovation
|
||||
|
||||
**Wave 4 (Iterations 21+): Mastery & Experimentation**
|
||||
- Custom WebGL layers
|
||||
- Real-time data integration
|
||||
- Novel visualization techniques
|
||||
- Focus: Pushing Mapbox boundaries
|
||||
|
||||
### **Improvement Metrics**
|
||||
|
||||
Each iteration should improve on at least one dimension:
|
||||
- **Visual Design**: Better colors, styling, visual hierarchy
|
||||
- **Interactivity**: New interaction patterns, smoother animations
|
||||
- **Data Handling**: More complex data, better transformations
|
||||
- **Performance**: Faster rendering, optimized expressions
|
||||
- **Features**: New Mapbox capabilities, creative techniques
|
||||
- **Code Quality**: Cleaner architecture, better patterns
|
||||
|
||||
## Mapbox-Specific Techniques
|
||||
|
||||
### **Globe Projection Features**
|
||||
```js
|
||||
// Atmosphere and space effects
|
||||
map.setFog({
|
||||
color: 'rgba(12, 20, 39, 0.9)',
|
||||
'high-color': 'rgba(36, 92, 223, 0.4)',
|
||||
'horizon-blend': 0.4,
|
||||
'space-color': '#000000',
|
||||
'star-intensity': 0.6
|
||||
});
|
||||
|
||||
// Globe-specific camera positioning
|
||||
map.flyTo({
|
||||
center: [lng, lat],
|
||||
zoom: 2,
|
||||
pitch: 45, // Tilt for 3D effect
|
||||
bearing: -17.6 // Rotation
|
||||
});
|
||||
```
|
||||
|
||||
### **Layer Types for Global Data**
|
||||
- **Heatmap**: Density visualization (temperature, population, incidents)
|
||||
- **Circle**: Point data with size/color encoding (cities, events, locations)
|
||||
- **Fill**: Choropleth maps (country-level statistics)
|
||||
- **Fill-extrusion**: 3D country/region extrusions
|
||||
- **Line**: Connections, routes, boundaries
|
||||
- **Symbol**: Labels, custom markers, icons
|
||||
|
||||
### **Expression Patterns**
|
||||
```js
|
||||
// Data-driven styling with expressions
|
||||
'circle-radius': [
|
||||
'interpolate',
|
||||
['linear'],
|
||||
['get', 'value'],
|
||||
0, 5,
|
||||
1000, 20
|
||||
]
|
||||
|
||||
// Conditional styling
|
||||
'circle-color': [
|
||||
'step',
|
||||
['get', 'value'],
|
||||
'#green', 100,
|
||||
'#yellow', 500,
|
||||
'#red'
|
||||
]
|
||||
|
||||
// Zoom-based styling
|
||||
'circle-opacity': [
|
||||
'interpolate',
|
||||
['linear'],
|
||||
['zoom'],
|
||||
1, 0.8,
|
||||
5, 1
|
||||
]
|
||||
```
|
||||
|
||||
## Web Research Directive
|
||||
|
||||
### **For Each Iteration**
|
||||
|
||||
**Before Generating:**
|
||||
1. Fetch assigned Mapbox web URL
|
||||
2. Analyze the content for:
|
||||
- New Mapbox GL JS techniques or APIs
|
||||
- Layer types and styling patterns
|
||||
- Expression syntax examples
|
||||
- Interaction patterns
|
||||
- Performance considerations
|
||||
3. Identify 1-3 specific learnings to apply
|
||||
4. Plan how to integrate with globe projection
|
||||
|
||||
**During Generation:**
|
||||
1. Apply new technique from web source
|
||||
2. Maintain globe projection focus
|
||||
3. Document what was learned
|
||||
4. Ensure genuine improvement
|
||||
|
||||
**After Generation:**
|
||||
1. Document web source in README
|
||||
2. Explain improvement over previous iteration
|
||||
3. Note future exploration opportunities
|
||||
|
||||
## Data Strategy
|
||||
|
||||
### **Embedded Data Requirements**
|
||||
- Use realistic, meaningful global datasets
|
||||
- Data appropriate for globe-scale visualization
|
||||
- Include enough features to demonstrate technique (50-500 typically)
|
||||
- Proper GeoJSON format with valid coordinates
|
||||
- Include metadata for popups and legends
|
||||
|
||||
### **Example Data Domains**
|
||||
- **Economic**: GDP, trade, wages, development indices
|
||||
- **Climate**: Temperature, precipitation, emissions
|
||||
- **Social**: Population, education, health metrics
|
||||
- **Infrastructure**: Cities, airports, networks
|
||||
- **Natural**: Earthquakes, volcanoes, resources
|
||||
- **Political**: Elections, conflicts, boundaries
|
||||
|
||||
## Ultra-Thinking Directive
|
||||
|
||||
Before each iteration, deeply consider:
|
||||
|
||||
**Web Source Integration:**
|
||||
- What Mapbox technique does the URL teach?
|
||||
- How can this improve globe visualizations?
|
||||
- What makes this technique globe-appropriate?
|
||||
- How can I adapt this learning creatively?
|
||||
|
||||
**Progressive Improvement:**
|
||||
- What was limiting in the previous iteration?
|
||||
- How does this represent genuine progress?
|
||||
- What new Mapbox capability am I adding?
|
||||
- How am I building on accumulated knowledge?
|
||||
|
||||
**Globe-Specific Design:**
|
||||
- Does this work well on a spherical projection?
|
||||
- How does data appear from different angles?
|
||||
- Are interactions intuitive for globe navigation?
|
||||
- How do layers compose in 3D space?
|
||||
|
||||
**Technical Excellence:**
|
||||
- Am I using Mapbox expressions correctly?
|
||||
- Is performance optimized for globe rendering?
|
||||
- Are layer types appropriate for the data?
|
||||
- What edge cases should I handle?
|
||||
|
||||
**Visual Communication:**
|
||||
- Does the globe effectively show global patterns?
|
||||
- Are visual encodings clear and intuitive?
|
||||
- Do colors work on the dark globe style?
|
||||
- What story does this visualization tell?
|
||||
|
||||
## Success Criteria
|
||||
|
||||
A successful Mapbox globe iteration demonstrates:
|
||||
1. **Web Learning Applied**: Specific Mapbox technique from URL implemented correctly
|
||||
2. **Measurable Improvement**: Clear advancement over previous iteration
|
||||
3. **Globe-Appropriate**: Design works well with spherical projection
|
||||
4. **Technical Quality**: Proper Mapbox patterns, performant rendering
|
||||
5. **Visual Excellence**: Professional design, effective data communication
|
||||
6. **Self-Contained**: Works perfectly as standalone application
|
||||
7. **Documented**: Clear explanation of improvements and web source attribution
|
||||
|
||||
## File Organization Standards
|
||||
|
||||
### **index.html**
|
||||
- Minimal, semantic HTML structure
|
||||
- Mapbox GL JS v3.0+ CDN links
|
||||
- Style block for overlays and UI
|
||||
- Script loading order: data → main
|
||||
|
||||
### **src/index.js**
|
||||
- Map initialization with globe projection
|
||||
- Fog/atmosphere configuration
|
||||
- Data source and layer setup
|
||||
- Interaction handlers
|
||||
- Control additions
|
||||
- Well-commented code
|
||||
|
||||
### **src/data/data.js**
|
||||
- Properly formatted GeoJSON
|
||||
- Realistic data values
|
||||
- Descriptive property names
|
||||
- Exposed as global variable
|
||||
|
||||
### **README.md**
|
||||
- Iteration number and title
|
||||
- Web source attribution
|
||||
- Techniques learned and applied
|
||||
- How to run locally
|
||||
- Data sources
|
||||
- Improvement over previous iteration
|
||||
|
||||
### **CLAUDE.md**
|
||||
- Local server commands
|
||||
- Code guidelines
|
||||
- Mapbox-specific patterns
|
||||
- Project structure notes
|
||||
|
||||
Generate globe visualizations that progressively evolve from basic global data displays to masterful, interactive 3D visualizations through systematic web-enhanced learning of Mapbox GL JS capabilities.
|
||||
|
|
@ -0,0 +1,270 @@
|
|||
{
|
||||
"priming_urls": [
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/guides/",
|
||||
"topic": "Mapbox GL JS Fundamentals",
|
||||
"description": "Core concepts and capabilities of Mapbox GL JS"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/globe/",
|
||||
"topic": "Globe Projection",
|
||||
"description": "3D globe view setup and configuration"
|
||||
},
|
||||
{
|
||||
"url": "https://www.mapbox.com/blog/globe-view",
|
||||
"topic": "Globe View Features",
|
||||
"description": "Overview of globe capabilities and use cases"
|
||||
}
|
||||
],
|
||||
|
||||
"foundation_urls": [
|
||||
{
|
||||
"iteration_range": [1, 5],
|
||||
"urls": [
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/api/map/",
|
||||
"topic": "Map Class",
|
||||
"description": "Core Map initialization and configuration"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/simple-map/",
|
||||
"topic": "Simple Map Setup",
|
||||
"description": "Basic map initialization patterns"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/geojson-line/",
|
||||
"topic": "GeoJSON Data",
|
||||
"description": "Working with GeoJSON data sources"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/circle-layer/",
|
||||
"topic": "Circle Layers",
|
||||
"description": "Creating point visualizations with circles"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/heatmap-layer/",
|
||||
"topic": "Heatmap Layers",
|
||||
"description": "Creating density visualizations with heatmaps"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/popup-on-hover/",
|
||||
"topic": "Popup Interactions",
|
||||
"description": "Adding interactive popups on hover"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/help/glossary/zoom-level/",
|
||||
"topic": "Zoom Levels",
|
||||
"description": "Understanding zoom-based styling"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/style-spec/sources/",
|
||||
"topic": "Data Sources",
|
||||
"description": "GeoJSON and other data source types"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"intermediate_urls": [
|
||||
{
|
||||
"iteration_range": [6, 12],
|
||||
"urls": [
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/style-spec/expressions/",
|
||||
"topic": "Mapbox Expressions",
|
||||
"description": "Data-driven styling with expressions"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/data-driven-circle-colors/",
|
||||
"topic": "Data-Driven Styling",
|
||||
"description": "Color and size based on data properties"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/choropleth/",
|
||||
"topic": "Choropleth Maps",
|
||||
"description": "Country/region-based visualizations"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/updating-choropleth/",
|
||||
"topic": "Dynamic Choropleth",
|
||||
"description": "Updating choropleth data dynamically"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/filter-markers/",
|
||||
"topic": "Data Filtering",
|
||||
"description": "Interactive data filtering techniques"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/color-switcher/",
|
||||
"topic": "Layer Styling",
|
||||
"description": "Dynamic style changes and themes"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/timeline-animation/",
|
||||
"topic": "Timeline Animation",
|
||||
"description": "Time-based data visualization"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/toggle-interaction-handlers/",
|
||||
"topic": "Interaction Handlers",
|
||||
"description": "Custom interaction controls"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/queryrenderedfeatures/",
|
||||
"topic": "Feature Queries",
|
||||
"description": "Querying visible features"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/popup-on-click/",
|
||||
"topic": "Click Interactions",
|
||||
"description": "Click-based popup and selections"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/measure-distances/",
|
||||
"topic": "Spatial Measurements",
|
||||
"description": "Measuring distances and areas"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/satellite-map/",
|
||||
"topic": "Map Styles",
|
||||
"description": "Different basemap styles for globe"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
"advanced_urls": [
|
||||
{
|
||||
"iteration_range": [13, 20],
|
||||
"urls": [
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/3d-buildings/",
|
||||
"topic": "3D Extrusions",
|
||||
"description": "Creating 3D extruded shapes"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/add-3d-model/",
|
||||
"topic": "3D Models",
|
||||
"description": "Adding custom 3D models to map"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/animate-camera-around-point/",
|
||||
"topic": "Camera Animation",
|
||||
"description": "Smooth camera movements and orbits"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/cluster/",
|
||||
"topic": "Point Clustering",
|
||||
"description": "Clustering large point datasets"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/animate-marker/",
|
||||
"topic": "Marker Animation",
|
||||
"description": "Animated markers and symbols"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/animate-point-along-line/",
|
||||
"topic": "Path Animation",
|
||||
"description": "Animating objects along paths"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/custom-marker-icons/",
|
||||
"topic": "Custom Markers",
|
||||
"description": "Custom marker symbols and icons"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/drag-a-point/",
|
||||
"topic": "Draggable Features",
|
||||
"description": "Interactive draggable map elements"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/timeline-animation/",
|
||||
"topic": "Complex Animations",
|
||||
"description": "Multi-step timeline animations"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/live-update-feature/",
|
||||
"topic": "Real-Time Updates",
|
||||
"description": "Dynamically updating features"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/vector-source/",
|
||||
"topic": "Vector Tiles",
|
||||
"description": "Working with vector tile sources"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/hillshade/",
|
||||
"topic": "Terrain Visualization",
|
||||
"description": "Hillshade and terrain effects"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
"expert_urls": [
|
||||
{
|
||||
"iteration_range": [21, 999],
|
||||
"urls": [
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/custom-style-layer/",
|
||||
"topic": "Custom Style Layers",
|
||||
"description": "Creating custom WebGL rendering layers"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/game-controls/",
|
||||
"topic": "Advanced Controls",
|
||||
"description": "Custom control implementations"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/mapbox-gl-draw/",
|
||||
"topic": "Drawing Tools",
|
||||
"description": "Interactive drawing and editing"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/data-join/",
|
||||
"topic": "Advanced Data Joining",
|
||||
"description": "Complex data joining patterns"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/3d-terrain/",
|
||||
"topic": "3D Terrain",
|
||||
"description": "Terrain-3D visualization"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/sky-api/",
|
||||
"topic": "Sky Layer",
|
||||
"description": "Custom sky and atmosphere effects"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/video-on-a-map/",
|
||||
"topic": "Custom Media Layers",
|
||||
"description": "Video and dynamic media layers"
|
||||
},
|
||||
{
|
||||
"url": "https://docs.mapbox.com/mapbox-gl-js/example/measure-distances/",
|
||||
"topic": "Spatial Analysis",
|
||||
"description": "Advanced spatial measurements"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"web_search_templates": [
|
||||
"Mapbox GL JS {technique} example",
|
||||
"Mapbox globe {feature} tutorial",
|
||||
"Mapbox {layer_type} best practices",
|
||||
"Mapbox expressions {use_case}",
|
||||
"Mapbox 3D {element} implementation",
|
||||
"Mapbox globe performance {context}",
|
||||
"Mapbox data visualization {chart_type}",
|
||||
"Mapbox interactive {feature} globe"
|
||||
],
|
||||
|
||||
"url_selection_strategy": {
|
||||
"mode": "progressive",
|
||||
"description": "Select URLs based on iteration number and globe-specific learning",
|
||||
"fallback": "dynamic_search",
|
||||
"avoid_duplicates": true,
|
||||
"track_used_urls": true
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue