681 lines
22 KiB
Markdown
681 lines
22 KiB
Markdown
# 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.
|
|
|
|
---
|
|
|
|
## Shared Architecture (Added 2025)
|
|
|
|
### **Problem Identified**
|
|
Iterations 10-13 encountered critical failures:
|
|
- **Invalid Mapbox tokens**: Placeholder strings instead of valid tokens
|
|
- **Layer type mismatches**: Fill layers (requires Polygons) used with Point data
|
|
- **Inconsistent data generation**: Each demo generated data differently
|
|
- **No validation**: Silent failures with no error messages
|
|
|
|
### **Solution: Shared Module Architecture**
|
|
|
|
A centralized architecture was created in `mapbox_test/shared/` to ensure reliability across all visualizations:
|
|
|
|
```
|
|
mapbox_test/
|
|
├── shared/ # Shared infrastructure for all demos
|
|
│ ├── mapbox-config.js # Token management & validation
|
|
│ ├── data-generator.js # Unified data generation
|
|
│ └── layer-factory.js # Best-practice layer creation
|
|
│
|
|
├── mapbox_globe_10/ # Uses shared architecture
|
|
├── mapbox_globe_11/ # Uses shared architecture
|
|
├── mapbox_globe_12/ # Uses shared architecture
|
|
├── mapbox_globe_13/ # Uses shared architecture
|
|
└── mapbox_globe_14/ # Reference implementation
|
|
```
|
|
|
|
#### **1. mapbox-config.js** - Token Management
|
|
- Centralized token storage (uses validated token from globe_14)
|
|
- Automatic validation on startup
|
|
- User-friendly error messages for invalid tokens
|
|
- Auto-applies token to mapboxgl when imported
|
|
|
|
```javascript
|
|
import { MAPBOX_CONFIG } from '../shared/mapbox-config.js';
|
|
MAPBOX_CONFIG.applyToken(); // Validates and applies
|
|
```
|
|
|
|
#### **2. data-generator.js** - Unified Data Generation
|
|
- 60+ countries with accurate geographic centroids
|
|
- Consistent Point geometry structure (no Polygon issues)
|
|
- Realistic vaccine-specific metrics
|
|
- WHO regions and income level classifications
|
|
- Exports: `generateVaccineData(vaccineType)`
|
|
|
|
```javascript
|
|
import { generateVaccineData } from '../shared/data-generator.js';
|
|
const polioData = generateVaccineData('polio');
|
|
```
|
|
|
|
Supported vaccine types:
|
|
- `'polio'` - Coverage by year (1980-2020), eradication status
|
|
- `'measles'` - Dose 1/2 coverage, cases, deaths (2023)
|
|
- `'smallpox'` - Endemic status by decade (1950-1980)
|
|
- `'dtp3'` - Coverage, zero-dose children, mortality rates
|
|
- `'hpv'` - Coverage, cancer prevention metrics
|
|
|
|
#### **3. layer-factory.js** - Best-Practice Layers
|
|
- Pre-configured circle layers (work with Point geometries)
|
|
- Color scales: coverage, diverging, purple, blue-orange
|
|
- Atmosphere presets: default, dark, medical, purple
|
|
- Helper methods: legends, popups, hover effects
|
|
|
|
```javascript
|
|
import { LayerFactory, COLOR_SCALES } from '../shared/layer-factory.js';
|
|
|
|
const factory = new LayerFactory(map);
|
|
|
|
// Apply atmosphere
|
|
factory.applyGlobeAtmosphere({ theme: 'medical' });
|
|
|
|
// Create optimized circle layer
|
|
const layer = factory.createCircleLayer({
|
|
id: 'vaccine-circles',
|
|
source: 'vaccine-data',
|
|
sizeProperty: 'population',
|
|
colorProperty: 'coverage_2020',
|
|
colorScale: 'coverage'
|
|
});
|
|
```
|
|
|
|
### **Migration Pattern**
|
|
|
|
**Updated HTML:**
|
|
```html
|
|
<!-- Load shared Mapbox configuration BEFORE main script -->
|
|
<script type="module">
|
|
import { MAPBOX_CONFIG } from '../shared/mapbox-config.js';
|
|
MAPBOX_CONFIG.applyToken(); // Validates and applies token
|
|
</script>
|
|
|
|
<!-- Load main application -->
|
|
<script type="module" src="src/index.js"></script>
|
|
```
|
|
|
|
**Updated JavaScript:**
|
|
```javascript
|
|
import { MAPBOX_CONFIG } from '../../shared/mapbox-config.js';
|
|
import { generateVaccineData } from '../../shared/data-generator.js';
|
|
import { LayerFactory, COLOR_SCALES } from '../../shared/layer-factory.js';
|
|
|
|
// Generate data (Point geometries)
|
|
const vaccineData = generateVaccineData('polio');
|
|
|
|
// Initialize map with validated config
|
|
const map = new mapboxgl.Map({
|
|
container: 'map',
|
|
...MAPBOX_CONFIG.getMapOptions({
|
|
center: [20, 20],
|
|
zoom: 1.5
|
|
})
|
|
});
|
|
|
|
map.on('load', () => {
|
|
const factory = new LayerFactory(map);
|
|
factory.applyGlobeAtmosphere({ theme: 'medical' });
|
|
|
|
// Add data source
|
|
map.addSource('vaccine-data', {
|
|
type: 'geojson',
|
|
data: vaccineData
|
|
});
|
|
|
|
// Create circle layer (not fill!)
|
|
const layer = factory.createCircleLayer({
|
|
id: 'vaccine-circles',
|
|
source: 'vaccine-data',
|
|
colorProperty: 'coverage_2020',
|
|
colorScale: 'coverage'
|
|
});
|
|
|
|
map.addLayer(layer);
|
|
});
|
|
```
|
|
|
|
### **Key Benefits**
|
|
✅ **Reliability**: Valid token guaranteed across all demos
|
|
✅ **Consistency**: All demos use same data structure and patterns
|
|
✅ **Maintainability**: Fix bugs in shared modules, not individual demos
|
|
✅ **Performance**: Best-practice layers with optimized expressions
|
|
✅ **Validation**: Automatic error detection and user feedback
|
|
✅ **Scalability**: Easy to add new vaccine types or demos
|
|
|
|
### **Documentation**
|
|
Complete migration guide available at:
|
|
`mapbox_test/CRITICAL_FIXES_GUIDE.md`
|
|
|
|
### **Additional Fixes (Null Handling & Color Scales)**
|
|
|
|
**Problem**: Mapbox expressions failed when encountering null/undefined property values:
|
|
- Console errors: `Expected value to be of type number, but found null instead`
|
|
- Invalid filter configurations: `array expected, null found`
|
|
- Color scales semantically reversed (high coverage showed red instead of green)
|
|
|
|
**Solutions Applied**:
|
|
|
|
1. **Null Value Handling with Coalesce**:
|
|
- All `['get', 'property']` expressions wrapped with `['coalesce', ['get', 'property'], 0]`
|
|
- Applies to: size expressions, color expressions, filter expressions
|
|
- Defaults null/undefined to 0 to prevent expression failures
|
|
|
|
2. **Conditional Filter Assignment**:
|
|
- Layer factory only adds `filter` property when truthy (not null)
|
|
- Prevents Mapbox validation errors for null filters
|
|
|
|
3. **Color Scale Correction**:
|
|
- `coverageReverse` scale colors were backwards
|
|
- **Before**: 0% = green, 100% = red (inverted semantics)
|
|
- **After**: 0-20% = red (bad), 80-100% = green (good)
|
|
- Now correctly shows high coverage as green (positive) and low coverage as red (critical)
|
|
|
|
**Code Examples**:
|
|
|
|
```javascript
|
|
// Fixed: Color expression with coalesce
|
|
createColorExpression(property, scaleName) {
|
|
const expression = [
|
|
'interpolate',
|
|
['linear'],
|
|
['coalesce', ['get', property], 0] // ✅ Handles null values
|
|
];
|
|
// ... add color stops
|
|
return expression;
|
|
}
|
|
|
|
// Fixed: Conditional filter assignment
|
|
const layer = { id, type: 'circle', source, paint: {...} };
|
|
if (filter) { // ✅ Only add if not null
|
|
layer.filter = filter;
|
|
}
|
|
return layer;
|
|
|
|
// Fixed: coverageReverse scale
|
|
coverageReverse: {
|
|
domain: [0, 100],
|
|
colors: ['#d73027', '#fc8d59', '#fee08b', '#d9ef8b', '#91cf60', '#1a9850'],
|
|
// Red (0%) → Orange → Yellow → Lt.Green → Green (100%)
|
|
stops: [0, 20, 40, 60, 80, 100]
|
|
}
|
|
```
|
|
|
|
### **Status**
|
|
- **Fixed**: globe_10 (Polio), globe_11 (Measles), globe_12 (Smallpox), globe_13 (DTP3)
|
|
- **Null Handling**: All shared layer factory expressions now resilient to null values
|
|
- **Color Semantics**: Coverage scales correctly show green=good, red=bad
|
|
- **Reference**: globe_14 (HPV) - original working implementation
|
|
- **All demos now render correctly with visible, properly-colored data on the globe**
|