Files
MyClub/DOCS/VECTOR_MAPS_IMPLEMENTATION.md
Tomáš Dvořák 12cba639b9 upload
2025-10-16 13:32:05 +02:00

469 lines
11 KiB
Markdown

# Vector Maps Implementation with MapLibre GL JS & OpenMapTiles
## 🚀 Overview
This implementation uses **MapLibre GL JS** (open-source) with **OpenMapTiles** vector tiles to provide:
- **Better performance** - Vector tiles are smaller and faster
- **Sharp rendering** - Perfect on Retina/HiDPI displays
- **Dynamic styling** - Change colors and styles at runtime
- **Club color integration** - Automatic application of club colors to map elements
- **Custom style support** - Full control via Mapbox GL Style JSON
## 📦 What Was Added
### New Files
- `frontend/src/components/home/VectorMap.tsx` - Main vector map component
- `frontend/src/components/admin/VectorMapStyleSelector.tsx` - Admin UI for vector maps
- `VECTOR_MAPS_IMPLEMENTATION.md` - This documentation
### Dependencies Added
```json
{
"maplibre-gl": "^4.x.x",
"@types/maplibre-gl": "^4.x.x"
}
```
## 🎨 Features
### 1. Vector Map Styles
Four professional styles from MapTiler (based on OpenMapTiles):
| Style | Description | Best For |
|-------|-------------|----------|
| **Positron** | Clean light style | Data visualization, colored overlays |
| **Dark Matter** | Sleek dark theme | Modern interfaces, night mode |
| **OSM Bright** | Colorful OSM style | General purpose, vibrant look |
| **Basic** | Simple clean base | Minimal, professional |
### 2. Dynamic Club Color Integration
The vector map automatically applies your club colors to:
- **Marker pins** - Colored with primary club color
- **Water features** - Tinted with club color (subtle)
- **Custom elements** - Can be extended via style JSON
### 3. Custom Style Support
Advanced users can provide custom Mapbox GL Style JSON:
```typescript
<VectorMap
customStyleUrl="https://your-server.com/custom-style.json"
clubPrimaryColor="#e11d48"
// ... other props
/>
```
## 🛠️ Technical Details
### MapLibre GL JS
**Why MapLibre?**
- ✅ Open-source fork of Mapbox GL JS
- ✅ No vendor lock-in
- ✅ Free for all uses
- ✅ Active community development
- ✅ Compatible with Mapbox styles
### OpenMapTiles
**Data Source:**
- Vector tiles from MapTiler API (free tier available)
- Based on OpenStreetMap data
- Updated regularly
- Global coverage
**Performance:**
- Vector tiles are ~75% smaller than raster tiles
- Smooth zooming and rotation
- Client-side rendering
- GPU acceleration
## 📋 Usage
### Basic Usage
```typescript
import VectorMap from '../components/home/VectorMap';
<VectorMap
latitude={50.0755}
longitude={14.4378}
zoom={15}
clubName="FK Example"
address="Example Street 123, Prague"
mapStyle="positron"
clubPrimaryColor="#e11d48"
clubSecondaryColor="#3b82f6"
/>
```
### Props
```typescript
interface VectorMapProps {
latitude: number; // Required
longitude: number; // Required
zoom?: number; // Default: 15
address?: string; // Optional popup content
clubName?: string; // Optional popup content
mapStyle?: 'positron' | 'dark-matter' | 'osm-bright' | 'klokantech-basic';
height?: number; // Default: 400
clubPrimaryColor?: string; // Hex color for marker
clubSecondaryColor?: string; // Secondary color
customStyleUrl?: string; // Custom Mapbox GL Style JSON URL
}
```
## 🔑 API Key Setup
### For Development
The component includes a demo API key for testing.
### For Production
1. **Get a free API key** from [MapTiler](https://www.maptiler.com/)
- Sign up (free tier: 100,000 tile requests/month)
- Copy your API key
2. **Add to environment:**
Create/edit `.env` file:
```bash
REACT_APP_MAPTILER_KEY=your_api_key_here
```
3. **Rebuild the app:**
```bash
npm run build
```
## 🎨 Custom Styling
### Method 1: Modify Built-in Styles
Edit `VectorMap.tsx` and customize the `createCustomPositronStyle` function:
```typescript
const createCustomPositronStyle = (primaryColor?: string, secondaryColor?: string): any => {
return {
version: 8,
name: 'Custom Style',
sources: { /* ... */ },
layers: [
// Add/modify layers here
{
id: 'water',
type: 'fill',
paint: {
'fill-color': yourCustomColor
}
}
]
};
};
```
### Method 2: External Style JSON
Host your custom style JSON and reference it:
```typescript
<VectorMap
customStyleUrl="https://your-cdn.com/custom-positron.json"
/>
```
**Style JSON structure** (based on [Mapbox GL Style Spec](https://docs.mapbox.com/mapbox-gl-js/style-spec/)):
```json
{
"version": 8,
"name": "Custom Style",
"sources": {
"openmaptiles": {
"type": "vector",
"url": "https://api.maptiler.com/tiles/v3/tiles.json?key=YOUR_KEY"
}
},
"layers": [
{
"id": "background",
"type": "background",
"paint": { "background-color": "#f8f8f8" }
},
{
"id": "water",
"type": "fill",
"source": "openmaptiles",
"source-layer": "water",
"paint": { "fill-color": "#your-color" }
}
// ... more layers
]
}
```
### Method 3: Fork Positron GL Style
1. Clone the repository:
```bash
git clone https://github.com/openmaptiles/positron-gl-style.git
```
2. Customize `style.json`
3. Host on your server or CDN
4. Reference in your app
## 🎯 Integration with Existing System
### Option 1: Replace Existing Maps
Update imports in your components:
```typescript
// Old
import ContactMap from '../components/home/ContactMap';
// New
import VectorMap from '../components/home/VectorMap';
// Usage stays similar
<VectorMap
latitude={lat}
longitude={lng}
clubPrimaryColor={settings.primary_color}
// ... same props
/>
```
### Option 2: Toggle Between Raster/Vector
Create a wrapper component:
```typescript
const AdaptiveMap: React.FC<MapProps> = (props) => {
const useVector = settings.use_vector_maps; // from settings
return useVector
? <VectorMap {...props} />
: <ContactMap {...props} />;
};
```
## 📊 Performance Comparison
### Vector Maps (MapLibre GL)
- **Initial Load:** 150-200 KB (tiles + library)
- **Per Zoom:** 20-50 KB (vector tiles)
- **Rendering:** GPU-accelerated
- **Zoom Quality:** Always sharp
- **Customization:** Full runtime control
### Raster Maps (Leaflet)
- **Initial Load:** 100 KB (library only)
- **Per Zoom:** 100-200 KB (PNG tiles)
- **Rendering:** Image-based
- **Zoom Quality:** Pixelated between levels
- **Customization:** Limited to tile source
**Verdict:** Vector maps are faster after initial load and provide better visual quality.
## 🌍 Self-Hosting Tiles (Advanced)
For complete independence from third-party services:
### 1. Set Up OpenMapTiles Server
```bash
# Clone OpenMapTiles
git clone https://github.com/openmaptiles/openmaptiles.git
cd openmaptiles
# Generate tiles for your region
./quickstart.sh czech-republic
# Start tile server
docker-compose up -d
```
### 2. Update VectorMap Component
```typescript
const TILE_SERVER = 'http://your-server.com';
sources: {
'openmaptiles': {
type: 'vector',
url: `${TILE_SERVER}/tiles.json`
}
}
```
### Benefits of Self-Hosting:
- ✅ No API key required
- ✅ No request limits
- ✅ Full data control
- ✅ Offline capability
- ❌ Requires server maintenance
## 🎨 Club Color Examples
### Red Club (e.g., Slavia Prague)
```typescript
<VectorMap
mapStyle="positron"
clubPrimaryColor="#e11d48"
clubSecondaryColor="#ffffff"
/>
```
Result: Red markers on light map, subtle red tint on water
### Blue Club (e.g., Slovan Liberec)
```typescript
<VectorMap
mapStyle="dark-matter"
clubPrimaryColor="#3b82f6"
clubSecondaryColor="#60a5fa"
/>
```
Result: Blue markers on dark map, modern look
### Green Club
```typescript
<VectorMap
mapStyle="osm-bright"
clubPrimaryColor="#16a34a"
clubSecondaryColor="#fbbf24"
/>
```
Result: Green markers on colorful map
## 🐛 Troubleshooting
### Map Not Loading
**Check browser console for errors:**
1. **API Key Issue:**
```
Error: HTTP 403 - Unauthorized
```
Solution: Add valid `REACT_APP_MAPTILER_KEY` to `.env`
2. **Network Error:**
```
Error: Failed to fetch tiles
```
Solution: Check internet connection, firewall settings
3. **Style Loading Error:**
```
Error: Failed to parse style
```
Solution: Validate your custom style JSON
### Blank Map
- Verify coordinates are valid (lat: -90 to 90, lng: -180 to 180)
- Check zoom level (1-20)
- Ensure API key has not exceeded quota
### Marker Not Visible
- Check `clubPrimaryColor` is a valid color
- Ensure marker color contrasts with map style
- Verify marker is within viewport
### Performance Issues
- Reduce zoom level for overview maps
- Use simpler map style (e.g., 'klokantech-basic')
- Limit number of map instances per page
## 📱 Mobile Optimization
Vector maps are automatically mobile-optimized:
- ✅ Touch gestures (pinch, pan, rotate)
- ✅ Responsive sizing
- ✅ Efficient data loading
- ✅ GPU acceleration on mobile
**Tips:**
- Use lower zoom levels on mobile (12-14 instead of 15-17)
- Consider disabling rotation on mobile
- Test on actual devices, not just desktop browser
## 🔮 Future Enhancements
Potential additions:
1. **Multiple Markers** - Show multiple club locations
2. **Custom Marker Icons** - Use club logo as marker
3. **Heatmaps** - Show fan distribution
4. **3D Buildings** - Add depth to maps
5. **Route Planning** - Show directions to stadium
6. **Catchment Areas** - Draw radius around stadium
7. **Animation** - Animate markers and transitions
8. **Clustering** - Group nearby markers
## 📚 Resources
### Documentation
- [MapLibre GL JS Docs](https://maplibre.org/maplibre-gl-js-docs/)
- [Mapbox GL Style Spec](https://docs.mapbox.com/mapbox-gl-js/style-spec/)
- [OpenMapTiles Schema](https://openmaptiles.org/schema/)
- [Positron GL Style](https://github.com/openmaptiles/positron-gl-style)
### Tools
- [Maputnik Style Editor](https://maputnik.github.io/) - Visual style editor
- [MapTiler Cloud](https://www.maptiler.com/) - Hosted tiles
- [OpenMapTiles](https://openmaptiles.org/) - Self-hosted solution
### Examples
- [MapLibre Examples](https://maplibre.org/maplibre-gl-js-docs/example/)
- [Vector Tile Style Gallery](https://openmaptiles.org/styles/)
## ✅ Checklist for Production
- [ ] Obtain MapTiler API key
- [ ] Add `REACT_APP_MAPTILER_KEY` to `.env`
- [ ] Test all map styles
- [ ] Verify club colors are applied correctly
- [ ] Test on mobile devices
- [ ] Check performance with browser DevTools
- [ ] Monitor API usage in MapTiler dashboard
- [ ] Consider self-hosting for high-traffic sites
- [ ] Add error boundaries for graceful failures
- [ ] Document custom styles if used
## 🎯 Migration Path
### Phase 1: Parallel Run (Recommended)
- Keep existing Leaflet maps
- Add vector maps as opt-in feature
- A/B test with users
- Monitor performance and feedback
### Phase 2: Gradual Rollout
- Enable vector maps for new features
- Offer toggle in admin settings
- Migrate high-traffic pages first
### Phase 3: Full Migration
- Default to vector maps
- Keep raster maps as fallback
- Remove Leaflet dependency
---
**Implementation Date:** 2025-10-10
**Technology:** MapLibre GL JS 4.x + OpenMapTiles
**License:** Open Source (BSD-3-Clause)
**Status:** ✅ Ready for Integration