Routen-Detailkarte: WebGL-Kontext-Leak gefixt → bleibt GL + zoomt auf Route
Eigentliche Ursache von 'Detailkarte zoomt nicht auf die Route': die Karte war auf dem Gerät gar keine GL-Karte mehr, sondern der Leaflet+OSM-RASTER-Fallback. Grund: _detailMap (GL-Kontext) wurde beim Schließen des Modals NIE freigegeben — jede geöffnete Route leakte einen WebGL-Kontext. Nach ~8 wirft MapLibre, und UI.map.create fällt auf Leaflet+OSM zurück. Genau die Mapnik-Kacheln aus Renés Screenshots (und die OSM-Attribution, die wir doch loswerden wollten). Fixes: - _detailMap modulweit + im onClose des Detail-Modals freigeben. - routes.js destroy(): _detailMap/_suggestMap/_searchMap + Mini-Maps beim Verlassen der Seite freigeben. - ui.js: Offscreen-Snapshot-Kontext nach 15s Leerlauf freigeben (hielt dauerhaft einen Kontext; Cache bleibt → kein Neu-Rendern). - _fitRouteMap fittet jetzt aufs 'load'/'idle'-Event der Karte (iOS verwirft ein fitBounds VOR dem ersten Render) statt nur auf feste Timeouts. Verifiziert (headless): 12 Detail-Öffnungen in Folge bleiben ALLE GL (Leaflet:false), GL-Canvas-Zahl bleibt bei 1–2 statt zu wachsen. Vorher leakte jede Öffnung einen Kontext.
This commit is contained in:
parent
d203ab17a8
commit
720971d252
7 changed files with 71 additions and 30 deletions
|
|
@ -937,7 +937,7 @@ const UI = (() => {
|
|||
// ----------------------------------------------------------
|
||||
// TRACK-VORSCHAU-SNAPSHOT — ein Offscreen-GL-Kontext rendert PNGs (Basemap+Route)
|
||||
// ----------------------------------------------------------
|
||||
let _snapMap = null, _snapReady = null, _snapChain = Promise.resolve();
|
||||
let _snapMap = null, _snapReady = null, _snapChain = Promise.resolve(), _snapReleaseTimer = null;
|
||||
const _snapCache = new Map(); // key → data-URL
|
||||
const _EMPTY_FC = { type: 'FeatureCollection', features: [] };
|
||||
|
||||
|
|
@ -1001,15 +1001,29 @@ const UI = (() => {
|
|||
}));
|
||||
}
|
||||
|
||||
// Offscreen-GL-Kontext nach Leerlauf freigeben — nicht dauerhaft halten, sonst belegt
|
||||
// er einen der knappen iOS-WebGL-Kontexte und beschleunigt das Limit (Detailkarten
|
||||
// fielen dann auf Leaflet+OSM-Raster zurück). Der PNG-Cache bleibt → kein Neu-Rendern.
|
||||
function _releaseSnapMap() {
|
||||
_snapReleaseTimer = null;
|
||||
if (_snapMap) { try { _snapMap.remove(); } catch (e) {} _snapMap = null; }
|
||||
_snapReady = null;
|
||||
}
|
||||
|
||||
function _glSnapshot(track, opts = {}) {
|
||||
if (!_uiUseGL()) return Promise.resolve(null); // GL aus → SVG-Fallback beim Aufrufer
|
||||
if (!track || track.length < 2) return Promise.resolve(null);
|
||||
const key = opts.key || ('t' + track.length + ',' + track[0].lat + ',' + track[0].lon + ',' +
|
||||
track[track.length - 1].lat + ',' + track[track.length - 1].lon);
|
||||
if (_snapCache.has(key)) return Promise.resolve(_snapCache.get(key));
|
||||
if (_snapReleaseTimer) { clearTimeout(_snapReleaseTimer); _snapReleaseTimer = null; }
|
||||
// Serielle Verarbeitung am gemeinsamen Offscreen-Kontext.
|
||||
const run = _snapChain.then(() => _renderSnap(track, key)).catch(() => null);
|
||||
_snapChain = run.catch(() => {});
|
||||
run.then(() => {
|
||||
if (_snapReleaseTimer) clearTimeout(_snapReleaseTimer);
|
||||
_snapReleaseTimer = setTimeout(_releaseSnapMap, 15000);
|
||||
});
|
||||
return run;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue