9.5 KiB
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
- OSM (OpenStreetMap) - Raster tiles from OSM
- Streets - Stadia Maps Alidade Smooth style
- Satellite - Esri World Imagery
- Dark - Stadia Maps dark theme
- 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
maplibrecontroller when enabled - Uses
mapscontroller 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 dependencyconfig/importmap.rb- Pinned maplibre-gl packageapp/views/layouts/map.html.erb- Conditional CSS loadingapp/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:
- Routes/Polylines - Speed-colored route rendering
- Tracks - GPS track visualization
- Heatmap - Density visualization (easier in MapLibre - native support!)
- Fog of War - Canvas overlay showing explored areas
- Scratch Map - Visited countries overlay
- Areas - User-defined geographic areas
- Visits - Location visit detection and display
- Photos - Geotagged photo markers
- Live Mode - Real-time GPS streaming
- Family Members - Real-time family location sharing
- Location Search - Search and navigate to locations
- Drawing Tools - Create custom areas
- Layer Control - Show/hide different layers
- Settings Panel - Map configuration UI
- Calendar Panel - Date range selection
Usage Instructions
For Users
-
Default Mode (Leaflet):
- Navigate to
/mapas usual - All existing features work normally
- Navigate to
-
MapLibre Mode:
- Click "Switch to MapLibre" button in top-right
- Or add
?maplibre=trueto URL - See your GPS points on a modern WebGL-powered map
-
Switching Back:
- Click "Switch to Leaflet" button
- Or add
?maplibre=falseto URL - Return to full-featured Leaflet mode
For Developers
Testing the Implementation
# 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
-
Add to maplibre_controller.js:
// Example: Adding a new feature addNewFeature() { // Your MapLibre implementation } -
Check data availability:
- All data attributes from Leaflet controller are available
- Access via
this.element.dataset.xxx
-
Use MapLibre APIs:
- Sources:
this.map.addSource() - Layers:
this.map.addLayer() - Events:
this.map.on()
- Sources:
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
-
Better Performance:
- Hardware-accelerated WebGL rendering
- Smoother with large datasets (10,000+ points)
- Better mobile performance
-
Modern Features:
- Native vector tile support
- Built-in heatmap layer
- 3D terrain support (future)
- Better style expressions
-
Active Development:
- Regular updates and improvements
- Growing community
- Better documentation
Leaflet Advantages (Why Keep It)
-
Feature Complete:
- All existing features work
- Extensive plugin ecosystem
- Mature and stable
-
Simpler API:
- Easier to understand
- More examples available
- Faster development
-
Lower Resource Usage:
- Canvas-based rendering
- Lower GPU requirements
- Better for older devices
Architecture Notes
Controller Inheritance
Both controllers extend BaseController:
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 keydata-coordinates- GPS points arraydata-tracks- Track datadata-user_settings- User preferencesdata-features- Enabled featuresdata-user_theme- Dark/light theme
Separation of Concerns
- Leaflet:
maps_controller.js+ helper files inapp/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
- Family Members Controller: Expects
window.mapsController- needs adapter for MapLibre - Points Controller: May expect Leaflet-specific APIs
- Add Visit Controller: Drawing tools use Leaflet.draw
- No Session Persistence: Toggle preference not saved (yet)
Configuration
User Settings (Respected by MapLibre)
{
"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:
@features = {
maplibre_enabled: true,
maplibre_default: false # Make MapLibre the default
}
Resources
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:
- Check browser console for errors
- Verify MapLibre CSS is loaded
- Check importmap configuration
- Test with
?maplibre=falseto confirm Leaflet still works