mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-11 01:31:39 -05:00
332 lines
9.5 KiB
Markdown
332 lines
9.5 KiB
Markdown
# MapLibre Implementation Guide
|
|
|
|
## Overview
|
|
|
|
We've successfully implemented MapLibre GL JS as a toggleable alternative to Leaflet in Dawarich. Users can now switch between the two mapping engines using a query parameter or UI toggle button.
|
|
|
|
## What's Been Implemented
|
|
|
|
### 1. Package Installation
|
|
|
|
- **MapLibre GL JS v5.10.0** added to npm dependencies
|
|
- Pinned to Rails importmap for asset management
|
|
- CSS loaded conditionally based on map engine selection
|
|
|
|
### 2. MapLibre Controller
|
|
|
|
Created a new Stimulus controller (`app/javascript/controllers/maplibre_controller.js`) that provides:
|
|
|
|
#### Core Features Implemented
|
|
|
|
- ✅ **Map Initialization** - Basic MapLibre map with center/zoom
|
|
- ✅ **Navigation Controls** - Pan, zoom, rotate controls
|
|
- ✅ **Scale Control** - Metric/Imperial units based on user settings
|
|
- ✅ **Geolocate Control** - User location tracking
|
|
- ✅ **Fullscreen Control** - Fullscreen map view
|
|
- ✅ **Points Display** - All GPS points rendered as circle markers
|
|
- ✅ **Popups** - Click markers to view details (timestamp, battery, altitude, speed, country)
|
|
- ✅ **Hover Effects** - Cursor changes on point hover
|
|
- ✅ **Auto-fit Bounds** - Map automatically fits to show all points
|
|
- ✅ **Theme Support** - Dark/light map styles based on user theme
|
|
|
|
#### Map Styles Available
|
|
|
|
1. **OSM (OpenStreetMap)** - Raster tiles from OSM
|
|
2. **Streets** - Stadia Maps Alidade Smooth style
|
|
3. **Satellite** - Esri World Imagery
|
|
4. **Dark** - Stadia Maps dark theme
|
|
5. **Light** - OpenStreetMap light theme
|
|
|
|
### 3. Toggle Mechanism
|
|
|
|
#### Query Parameter Method
|
|
```
|
|
http://localhost:3000/map?maplibre=true # Use MapLibre
|
|
http://localhost:3000/map?maplibre=false # Use Leaflet
|
|
```
|
|
|
|
#### UI Toggle Button
|
|
- Fixed position button in top-right corner (below navbar)
|
|
- Shows "Switch to MapLibre" or "Switch to Leaflet" based on current engine
|
|
- Maintains current date range when switching
|
|
- Uses DaisyUI button styling for consistency
|
|
|
|
### 4. Conditional Loading
|
|
|
|
The implementation conditionally loads CSS and controllers based on the `maplibre` parameter:
|
|
|
|
**Layout Changes** (`app/views/layouts/map.html.erb`):
|
|
- Loads MapLibre CSS when `?maplibre=true`
|
|
- Loads Leaflet CSS + Leaflet.draw CSS otherwise
|
|
|
|
**View Changes** (`app/views/map/index.html.erb`):
|
|
- Uses `maplibre` controller when enabled
|
|
- Uses `maps` controller otherwise
|
|
- Hides fog of war element for MapLibre (not yet implemented)
|
|
|
|
## File Changes Summary
|
|
|
|
### New Files
|
|
- `app/javascript/controllers/maplibre_controller.js` - MapLibre Stimulus controller
|
|
|
|
### Modified Files
|
|
- `package.json` - Added maplibre-gl dependency
|
|
- `config/importmap.rb` - Pinned maplibre-gl package
|
|
- `app/views/layouts/map.html.erb` - Conditional CSS loading
|
|
- `app/views/map/index.html.erb` - Toggle button and conditional controller
|
|
|
|
## Current Capabilities
|
|
|
|
### ✅ Working Features (MapLibre)
|
|
- Map rendering with OpenStreetMap tiles
|
|
- Point markers (all GPS points)
|
|
- Navigation controls (zoom, pan)
|
|
- Scale control
|
|
- Geolocate control
|
|
- Fullscreen control
|
|
- Click popups with point details
|
|
- Auto-fit to bounds
|
|
- Theme-based map styles
|
|
- Toggle between engines
|
|
|
|
### ⏳ Not Yet Implemented (MapLibre)
|
|
These Leaflet features need to be ported to MapLibre:
|
|
|
|
1. **Routes/Polylines** - Speed-colored route rendering
|
|
2. **Tracks** - GPS track visualization
|
|
3. **Heatmap** - Density visualization (easier in MapLibre - native support!)
|
|
4. **Fog of War** - Canvas overlay showing explored areas
|
|
5. **Scratch Map** - Visited countries overlay
|
|
6. **Areas** - User-defined geographic areas
|
|
7. **Visits** - Location visit detection and display
|
|
8. **Photos** - Geotagged photo markers
|
|
9. **Live Mode** - Real-time GPS streaming
|
|
10. **Family Members** - Real-time family location sharing
|
|
11. **Location Search** - Search and navigate to locations
|
|
12. **Drawing Tools** - Create custom areas
|
|
13. **Layer Control** - Show/hide different layers
|
|
14. **Settings Panel** - Map configuration UI
|
|
15. **Calendar Panel** - Date range selection
|
|
|
|
## Usage Instructions
|
|
|
|
### For Users
|
|
|
|
1. **Default Mode (Leaflet)**:
|
|
- Navigate to `/map` as usual
|
|
- All existing features work normally
|
|
|
|
2. **MapLibre Mode**:
|
|
- Click "Switch to MapLibre" button in top-right
|
|
- Or add `?maplibre=true` to URL
|
|
- See your GPS points on a modern WebGL-powered map
|
|
|
|
3. **Switching Back**:
|
|
- Click "Switch to Leaflet" button
|
|
- Or add `?maplibre=false` to URL
|
|
- Return to full-featured Leaflet mode
|
|
|
|
### For Developers
|
|
|
|
#### Testing the Implementation
|
|
|
|
```bash
|
|
# Start the Rails server
|
|
bundle exec rails server
|
|
|
|
# Visit the map page
|
|
open http://localhost:3000/map
|
|
|
|
# Test MapLibre mode
|
|
open http://localhost:3000/map?maplibre=true
|
|
```
|
|
|
|
#### Adding New MapLibre Features
|
|
|
|
1. **Add to maplibre_controller.js**:
|
|
```javascript
|
|
// Example: Adding a new feature
|
|
addNewFeature() {
|
|
// Your MapLibre implementation
|
|
}
|
|
```
|
|
|
|
2. **Check data availability**:
|
|
- All data attributes from Leaflet controller are available
|
|
- Access via `this.element.dataset.xxx`
|
|
|
|
3. **Use MapLibre APIs**:
|
|
- Sources: `this.map.addSource()`
|
|
- Layers: `this.map.addLayer()`
|
|
- Events: `this.map.on()`
|
|
|
|
## Next Steps
|
|
|
|
### Phase 1: Core Features (High Priority)
|
|
- [ ] Implement polylines/routes with speed colors
|
|
- [ ] Add heatmap layer (native MapLibre support)
|
|
- [ ] Port track visualization
|
|
- [ ] Implement layer control UI
|
|
|
|
### Phase 2: Advanced Features (Medium Priority)
|
|
- [ ] Fog of War custom layer
|
|
- [ ] Scratch map (visited countries)
|
|
- [ ] Areas and visits
|
|
- [ ] Photo markers
|
|
|
|
### Phase 3: Real-time Features (Low Priority)
|
|
- [ ] Live mode integration
|
|
- [ ] Family members layer
|
|
- [ ] WebSocket updates
|
|
|
|
### Phase 4: Tools & Interaction (Future)
|
|
- [ ] Drawing tools (maplibre-gl-draw)
|
|
- [ ] Location search integration
|
|
- [ ] Settings panel for MapLibre
|
|
|
|
## Performance Comparison
|
|
|
|
### Expected Benefits of MapLibre
|
|
|
|
1. **Better Performance**:
|
|
- Hardware-accelerated WebGL rendering
|
|
- Smoother with large datasets (10,000+ points)
|
|
- Better mobile performance
|
|
|
|
2. **Modern Features**:
|
|
- Native vector tile support
|
|
- Built-in heatmap layer
|
|
- 3D terrain support (future)
|
|
- Better style expressions
|
|
|
|
3. **Active Development**:
|
|
- Regular updates and improvements
|
|
- Growing community
|
|
- Better documentation
|
|
|
|
### Leaflet Advantages (Why Keep It)
|
|
|
|
1. **Feature Complete**:
|
|
- All existing features work
|
|
- Extensive plugin ecosystem
|
|
- Mature and stable
|
|
|
|
2. **Simpler API**:
|
|
- Easier to understand
|
|
- More examples available
|
|
- Faster development
|
|
|
|
3. **Lower Resource Usage**:
|
|
- Canvas-based rendering
|
|
- Lower GPU requirements
|
|
- Better for older devices
|
|
|
|
## Architecture Notes
|
|
|
|
### Controller Inheritance
|
|
|
|
Both controllers extend `BaseController`:
|
|
```javascript
|
|
import BaseController from "./base_controller";
|
|
export default class extends BaseController {
|
|
// Controller implementation
|
|
}
|
|
```
|
|
|
|
### Data Sharing
|
|
|
|
Both controllers receive identical data attributes:
|
|
- `data-api_key` - User API key
|
|
- `data-coordinates` - GPS points array
|
|
- `data-tracks` - Track data
|
|
- `data-user_settings` - User preferences
|
|
- `data-features` - Enabled features
|
|
- `data-user_theme` - Dark/light theme
|
|
|
|
### Separation of Concerns
|
|
|
|
- **Leaflet**: `maps_controller.js` + helper files in `app/javascript/maps/`
|
|
- **MapLibre**: `maplibre_controller.js` (self-contained for now)
|
|
- **Shared**: View templates detect which to load
|
|
|
|
## Technical Decisions
|
|
|
|
### Why Query Parameter?
|
|
- Simple to implement
|
|
- Easy to share URLs
|
|
- No database changes needed
|
|
- Can be enhanced with session storage later
|
|
|
|
### Why Separate Controller?
|
|
- Clean separation of concerns
|
|
- Easier to develop independently
|
|
- No risk of breaking Leaflet functionality
|
|
- Can eventually deprecate Leaflet if MapLibre is preferred
|
|
|
|
### Why Keep Leaflet?
|
|
- Zero-risk migration strategy
|
|
- Users can choose based on needs
|
|
- Fallback for unsupported features
|
|
- Plugin ecosystem still valuable
|
|
|
|
## Known Issues
|
|
|
|
1. **Family Members Controller**: Expects `window.mapsController` - needs adapter for MapLibre
|
|
2. **Points Controller**: May expect Leaflet-specific APIs
|
|
3. **Add Visit Controller**: Drawing tools use Leaflet.draw
|
|
4. **No Session Persistence**: Toggle preference not saved (yet)
|
|
|
|
## Configuration
|
|
|
|
### User Settings (Respected by MapLibre)
|
|
|
|
```json
|
|
{
|
|
"maps": {
|
|
"distance_unit": "km", // or "mi"
|
|
"url": "custom-tile-server-url"
|
|
},
|
|
"preferred_map_layer": "OSM" // or "Streets", "Satellite", etc.
|
|
}
|
|
```
|
|
|
|
### Feature Flags (Future)
|
|
|
|
Could add to `features` hash:
|
|
```ruby
|
|
@features = {
|
|
maplibre_enabled: true,
|
|
maplibre_default: false # Make MapLibre the default
|
|
}
|
|
```
|
|
|
|
## Resources
|
|
|
|
- [MapLibre GL JS Documentation](https://maplibre.org/maplibre-gl-js/docs/)
|
|
- [MapLibre Style Spec](https://maplibre.org/maplibre-style-spec/)
|
|
- [MapLibre Examples](https://maplibre.org/maplibre-gl-js/docs/examples/)
|
|
- [Migration from Mapbox](https://github.com/maplibre/maplibre-gl-js/blob/main/MIGRATION.md)
|
|
|
|
## Testing Checklist
|
|
|
|
Before deploying to production:
|
|
|
|
- [ ] Test point rendering with small dataset (< 100 points)
|
|
- [ ] Test point rendering with large dataset (> 10,000 points)
|
|
- [ ] Test on mobile devices
|
|
- [ ] Test theme switching (dark/light)
|
|
- [ ] Test with different date ranges
|
|
- [ ] Verify toggle button works in all scenarios
|
|
- [ ] Check browser console for errors
|
|
- [ ] Test with different map styles
|
|
- [ ] Verify user settings are respected
|
|
- [ ] Test fullscreen mode
|
|
- [ ] Test geolocate feature
|
|
|
|
## Support
|
|
|
|
For issues with the MapLibre implementation:
|
|
1. Check browser console for errors
|
|
2. Verify MapLibre CSS is loaded
|
|
3. Check importmap configuration
|
|
4. Test with `?maplibre=false` to confirm Leaflet still works
|