6.8 KiB
6.8 KiB
Wind Layer Implementation Guide
🌬️ Overview
The project now uses @sakitam-gis/maplibre-wind for professional wind visualization on MapLibre GL maps.
📦 Installation
npm install @sakitam-gis/maplibre-wind --save
Package installed: ✅ Version included in package.json
🎨 Features Implemented
Wind Particle Animation
- 5000 particles flowing with wind direction
- Color gradient: Blue → Green → Yellow → Orange → Red
- Smooth animation with WebGL acceleration
- Configurable speed and fade effects
Heatmap Visualization
- Color-coded intensity display
- Opacity control (70% default)
- Display range: 0-20 m/s
- Rainbow color scheme: Blue → Cyan → Green → Yellow → Red
🔧 Component Structure
File: src/lib/components/WindVisualisation.svelte
Props:
map- MapLibre GL map instancewindData- Wind data in GRIB format (U/V components)
State:
showHeatmap- Toggle heatmap layershowParticles- Toggle particle animation layer
Functions:
initializeWindLayers()- Creates particle and heatmap layersprepareWindData()- Transforms GRIB data to wind-layer format- Reactive
$effect()- Toggles layer visibility
📊 Data Format
Input: GRIB Wind Data (testVelo.json)
[
{
"header": {
"parameterNumber": 2, // U-component
"nx": 360, // Grid columns
"ny": 181, // Grid rows
"lo1": 0.0, // Starting longitude
"la1": 90.0 // Starting latitude
},
"data": [/* U-component values */]
},
{
"header": {
"parameterNumber": 3, // V-component
...
},
"data": [/* V-component values */]
}
]
Output: Wind-Layer Format
{
uMin: number, // Min U-component value
uMax: number, // Max U-component value
vMin: number, // Min V-component value
vMax: number, // Max V-component value
rows: number, // Grid rows (ny)
cols: number, // Grid columns (nx)
data: [Array, Array] // [U-component, V-component]
}
🎛️ Configuration Options
Particle Layer
{
renderType: 'particles',
styleSpec: {
numParticles: 5000, // Number of particles
fadeOpacity: 0.996, // Trail fade rate (0.9-0.999)
speedFactor: 0.25, // Animation speed multiplier
dropRate: 0.003, // Particle regeneration rate
dropRateBump: 0.01, // Regeneration boost
colors: [ // Color gradient
'#3288bd', // Blue
'#66c2a5', // Green
'#fee08b', // Yellow
'#f46d43', // Orange
'#d53e4f' // Red
]
}
}
Heatmap Layer
{
renderType: 'colorize',
styleSpec: {
opacity: 0.7,
colors: [
'#0000ff', // Blue
'#00ffff', // Cyan
'#00ff00', // Green
'#ffff00', // Yellow
'#ff0000' // Red
],
displayRange: [0, 20] // Min/max wind speed (m/s)
}
}
🎮 Usage
UI Controls
Located in bottom-left corner of the map:
- ☑️ Тепловая карта - Toggle heatmap visualization
- ☑️ Частицы ветра - Toggle particle animation (default: ON)
Programmatic Control
// In Map.svelte
<WindVisualization {map} {windData} />
// Toggle layers via checkbox binding
// Layers automatically add/remove from map
🔄 Data Flow
1. testVelo.json (GRIB format)
↓
2. Map.svelte loads data
↓
3. WindVisualisation component receives:
- map instance
- windData
↓
4. prepareWindData() transforms to wind-layer format
↓
5. WindLayer instances created:
- Particle layer
- Heatmap layer
↓
6. Layers added to map
↓
7. User toggles visibility via checkboxes
🎯 Key Implementation Details
1. Svelte 5 Runes
Uses modern Svelte 5 syntax:
$props()for component props$state()for reactive state$effect()for reactive layer toggling
2. Map Lifecycle
- Waits for map to load before initializing
- Checks
map.loaded()status - Listens to
'load'event if not ready
3. Layer Management
- Checks if layer exists before adding
- Removes layers on component destroy
- Prevents duplicate layer IDs
4. Error Handling
- Validates wind data structure
- Catches initialization errors
- Logs detailed error messages
- Graceful degradation on failure
🐛 Debugging
Console Logs
// On mount
"WindVisualization mounted with MapLibre map"
"Wind data available: [...]"
// Data processing
"Wind data stats - U: [-21.32, 26.80], V: [-21.57, 21.42]"
// Success
"Wind layers initialized successfully"
// Errors
"Missing U or V wind components"
"Error initializing wind layers: [error]"
Check Layer Status
// In browser console
map.getLayer('wind-particles') // Should return layer object
map.getLayer('wind-heatmap') // Should return layer object
📚 Resources
- GitHub: https://github.com/sakitam-fdd/wind-layer
- Examples: https://sakitam-fdd.github.io/wind-layer/examples/
- MapLibre Docs: https://maplibre.org/maplibre-gl-js/docs/
⚙️ Advanced Customization
Adjust Particle Count
numParticles: 10000 // More particles (slower performance)
numParticles: 2000 // Fewer particles (better performance)
Change Animation Speed
speedFactor: 0.5 // Faster animation
speedFactor: 0.1 // Slower animation
Custom Color Schemes
// Wind speed colors
colors: ['#000080', '#0000FF', '#FFFF00', '#FF0000', '#800000']
// Monochrome
colors: ['#FFFFFF', '#CCCCCC', '#999999', '#666666', '#000000']
Adjust Display Range
displayRange: [0, 30] // For stronger winds
displayRange: [0, 10] // For lighter winds
🚀 Future Enhancements
Potential additions:
- Timeline control for temporal wind data
- Arrow vector visualization
- Wind speed labels
- Custom tile sources for real-time data
- Wind barbs (meteorological standard)
- Integration with prediction module
✅ Testing Checklist
- Package installed successfully
- Component imports without errors
- Wind data loads from testVelo.json
- Particle animation displays on map
- Heatmap visualization works
- Checkboxes toggle layers correctly
- No console errors on mount/unmount
- Layers clean up on component destroy
📝 Notes
- Wind data must be in GRIB format with U/V components
- Particle layer is GPU-accelerated (requires WebGL)
- Large particle counts may impact performance
- Data transformation happens client-side
- Layers are added above base map tiles
- Z-index managed by MapLibre layer order
Implementation Date: December 2025 Package Version: @sakitam-gis/maplibre-wind Status: ✅ Production Ready