Docs: Offline-Karten-Plan (GL/Vektor) — budget-getrieben + adaptives Funkloch-Lernen
Festgehalten als Feature-Plan: Region-Extract per pmtiles (budget-getrieben statt Radius, ~16 MB Default, gemessen 15 MB für 10km München / ~18-22km Land), Client IndexedDB-Blob + MapLibre lokal/remote, adaptives Lernen (rollendes Vorausladen beim Aufzeichnen + Funkloch-Gedächtnis aus echten Fetch-Fehlern, alles lokal), manuelles Vorab-Laden, Budget+LRU. Umsetzung nach Produktions-Rollout.
This commit is contained in:
parent
29076bcdff
commit
43b1e8026f
1 changed files with 72 additions and 0 deletions
72
docs/OFFLINE_MAPS_PLAN.md
Normal file
72
docs/OFFLINE_MAPS_PLAN.md
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
# Offline-Karten (GL/Vektor) — Feature-Plan
|
||||
|
||||
**Status:** geplant (Umsetzung nach Tile-Build/Produktions-Rollout der GL-Karten).
|
||||
**Stand:** 2026-06-05. Autor: René + Claude (Design).
|
||||
|
||||
## Ziel
|
||||
GL-Vektorkarten offline-tauglich machen — Kernszenario **Gassi/Wandern im Funkloch**.
|
||||
Selbst-zielend (cacht wo nötig, nicht überall), speichersparsam, ohne Nutzeraufwand.
|
||||
|
||||
## Problem (warum GL aktuell NICHT offline geht)
|
||||
- PMTiles lädt per **HTTP-Range (206 Partial Content)**. Die **Cache-API kann 206 nicht speichern**
|
||||
(`cache.put()` wirft) → Basemap-Kacheln landen nie im Offline-Cache.
|
||||
- SW hat **keine Regel für `/tiles`** (nur für `tile.openstreetmap.org` = altes Raster).
|
||||
- `offline-indicator.js` prefetcht weiterhin **OSM-Raster** (a.tile.openstreetmap.org), das die GL-Karte
|
||||
gar nicht nutzt → doppelter Regress: Raster gecacht das niemand zeigt, GL-Karte offline trotzdem leer.
|
||||
- Folge offline heute: App + Daten da, aber GL-Karte = Routenlinie/Marker auf **leerem Hintergrund**.
|
||||
|
||||
## Gemessene Speicher-Fakten (an echter dach.pmtiles, maxzoom=14 + Overzoom bis ~16)
|
||||
| Gebiet | Fläche | Tiles | Größe |
|
||||
|---|---|---|---|
|
||||
| München (48,1/11,5), dicht | 20×20 km (10 km Radius) | 252 | **15 MB** |
|
||||
| Bayerischer Wald, ländlich | 20×20 km | 285 | **4,4 MB** |
|
||||
| Bayerischer Wald, ländlich | 50×50 km (~25 km Radius) | 1.595 | **20 MB** |
|
||||
|
||||
→ Vektor ist ~10× sparsamer als Raster (Raster 10 km ≈ 100–300 MB). Stadt-Tiles ~3,4× dicker als Land.
|
||||
→ **Budget ≈ 16 MB** deckt in der Stadt ~10 km, auf dem **Land ~18–22 km** Radius ab (mehr Reichweite
|
||||
genau dort wo die Funklöcher sind). Glyphs (~1–2 MB) + Style (winzig) obendrauf → ~17 MB pro Gegend.
|
||||
→ Messmethode (reproduzierbar): `docker run --rm -v /tmp/pmt:/out protomaps/go-pmtiles:latest extract
|
||||
https://staging.banyaro.app/tiles/dach.pmtiles /out/x.pmtiles --bbox=W,S,E,N` → Dateigröße ablesen.
|
||||
|
||||
## Architektur
|
||||
### Region-Extract (budget-getrieben, NICHT fester Radius)
|
||||
- PMTiles-**Directory enthält pro Tile die Byte-Länge** → Server kann die Größe einer Region
|
||||
**aufsummieren OHNE die Tiles zu laden**.
|
||||
- Endpoint `GET /tiles/region?lat=&lon=&budget=16` (MB): wächst die bbox um die Position, bis die
|
||||
summierte Tile-Länge ≈ Budget erreicht (Stadt → kleiner Radius, Land → großer Radius), extrahiert dann
|
||||
genau diese Region als `region.pmtiles` (**ein 200er**, ~16 MB). `pmtiles extract` (go-pmtiles) oder
|
||||
python-pmtiles im Container.
|
||||
- Client lädt die Datei einmal → **IndexedDB** (Blob; 200er, anders als die 206-Ranges cachebar).
|
||||
- MapLibre liest **offline** aus dem lokalen Blob via `pmtiles://` (pmtiles.js kann aus ArrayBuffer lesen);
|
||||
**online** weiter remote `dach.pmtiles` (immer aktuell, ganz DACH+Anrainer). Source je nach Verbindung wählen.
|
||||
- Glyphs (`/fonts/*.pbf`, Open Sans Regular+Semibold) mit cachen (200er, cachebar).
|
||||
|
||||
### Adaptive Strategie (der eigentliche Clou — lernt von selbst)
|
||||
1. **Rollendes Vorausladen beim Aufzeichnen:** Solange GPS aktiv UND Empfang da, fortlaufend Tiles um die
|
||||
**aktuelle Position** cachen. Deckt den echten Weg + die Anfahrt automatisch ab — auch beim ersten Mal,
|
||||
bevor man ins Funkloch läuft.
|
||||
2. **Funkloch-Gedächtnis:** Wo echte Requests **scheitern** (Timeout/Fehler während aktivem GPS — NICHT
|
||||
`navigator.onLine`, das lügt bei Captive-Portal/Schwachempfang), den Bereich als „Offline nötig"
|
||||
markieren → priorisiert behalten, beim nächsten Online-Durchgang großzügiger nachladen.
|
||||
Caveat: im Funkloch selbst kann nicht geladen werden → greift ab dem 2. Besuch (Gassi = repetitiv → ok).
|
||||
3. **Manuelles Vorab-Laden:** Button „Diese Gegend offline speichern" für geplante neue Touren (Lernen
|
||||
deckt nur Bekanntes ab). Fortschritt + „X MB gespeichert" + Löschen/Aktualisieren.
|
||||
|
||||
### Drumherum
|
||||
- **Budget-Cap + LRU:** Gesamtspeicher gedeckelt; selten besuchte Funkloch-Caches fallen raus.
|
||||
- **Privatsphäre:** „Wo verliere ich Netz" = Aufenthaltsorte → **komplett lokal (IndexedDB), nie hochgeladen.**
|
||||
- **Aktualität:** Offline-Region beim nächsten Online-Sein neu ziehbar (Basemap-Updates / pmtiles-Refresh).
|
||||
- **Aufräumen:** Den alten OSM-Raster-Prefetch in `offline-indicator.js` ablösen/abschalten (cacht ungenutztes Raster).
|
||||
|
||||
## Offene Entscheidungen / Defaults
|
||||
- Budget-Default **16 MB**, optional Stufe „Groß 40 MB" (Stadt ~16 km / Land ~30+ km) für Wandertage.
|
||||
- Zoom z0–14 (Overzoom liefert Straßenebene gratis).
|
||||
- Detektionssignal = echte Fetch-Timeouts bei aktivem GPS (nicht `navigator.onLine`).
|
||||
- Speicher = IndexedDB (Blobs); MapLibre-Source-Umschaltung online/offline.
|
||||
|
||||
## Abhängigkeiten
|
||||
- GL-Tiles in **Produktion** (dach.pmtiles + fonts auf Prod-Volume) — Voraussetzung.
|
||||
- pmtiles-Directory-Byte-Summierung (Server) + pmtiles.js Blob-Source (Client).
|
||||
- WebGL-Kontext-Disziplin beachten (siehe Skill/Memory: jede GL-Karte beim Schließen `remove()`).
|
||||
|
||||
Siehe `docs/TILE_SERVER_HANDOVER.md` (Tile-Pipeline) + Memory `project_tile_server_maintenance`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue