Seitenkarten auf MapLibre GL (Facade) — Runde 1: Giftköder + Verlorene
- map-gl-mini.js: Leaflet-kompatible MapLibre-Facade (createMap/svgMarker/circleMarker/ featureGroup-Wrapper mit setView/fitBounds/invalidateSize/addTo/bindPopup/openPopup/on/remove) - ui.js: UI.map.create/svgMarker/leafletMarker branchen auf GL (by_map_gl, Staging-Default), + UI.map.circleMarker/featureGroup, loadMapLibreUI - poison.js/lost.js: window.L-Guards entfernt, L.circleMarker→UI.map.circleMarker
This commit is contained in:
parent
9c4b999331
commit
5844f1ef51
9 changed files with 239 additions and 25 deletions
|
|
@ -446,6 +446,20 @@ const UI = (() => {
|
|||
attributionControl = false,
|
||||
darkFilter = false,
|
||||
} = options;
|
||||
|
||||
// MapLibre-GL-Seitenkarte (gleicher Style wie die Hauptkarte) — hinter by_map_gl-Flag.
|
||||
if (_uiUseGL()) {
|
||||
try {
|
||||
await loadMapLibreUI();
|
||||
_uiGL = true;
|
||||
const isDark = document.documentElement.dataset.theme === 'dark';
|
||||
return MapGLMini.createMap(containerId, { center, zoom, zoomControl, dark: isDark });
|
||||
} catch (e) {
|
||||
console.warn('GL-Seitenkarte nicht verfügbar — Fallback Leaflet:', e);
|
||||
}
|
||||
}
|
||||
_uiGL = false;
|
||||
|
||||
await loadLeaflet();
|
||||
const m = L.map(containerId, { zoomControl, attributionControl }).setView(center, zoom);
|
||||
|
||||
|
|
@ -483,6 +497,7 @@ const UI = (() => {
|
|||
|
||||
// SVG-Marker mit eigenem HTML (z.B. mit Pulse-Animation, Rotation, etc.)
|
||||
svgMarker(lat, lon, html, { size = 32, anchorY = null, className = '' } = {}) {
|
||||
if (_uiGL && window.MapGLMini) return MapGLMini.svgMarker(lat, lon, html, { size, anchorY });
|
||||
const icon = L.divIcon({
|
||||
className,
|
||||
html,
|
||||
|
|
@ -492,6 +507,18 @@ const UI = (() => {
|
|||
return L.marker([lat, lon], { icon });
|
||||
},
|
||||
|
||||
// Engine-neutral: Kreis-Marker (Leaflet L.circleMarker bzw. GL-HTML-Punkt).
|
||||
circleMarker(lat, lon, opts = {}) {
|
||||
if (_uiGL && window.MapGLMini) return MapGLMini.circleMarker(lat, lon, opts);
|
||||
return L.circleMarker([lat, lon], opts);
|
||||
},
|
||||
|
||||
// Engine-neutral: FeatureGroup (nur als Bounds-Container für fitBounds genutzt).
|
||||
featureGroup(markers = []) {
|
||||
if (_uiGL && window.MapGLMini) return MapGLMini.featureGroup(markers);
|
||||
return L.featureGroup(markers);
|
||||
},
|
||||
|
||||
// Feature-Flag-Status der Vektor-Basemap (für Karten, die ihren Basemap-Layer
|
||||
// selbst verwalten, z.B. pages/map.js).
|
||||
vectorEnabled() { return _vectorMapEnabled(); },
|
||||
|
|
@ -846,7 +873,47 @@ const UI = (() => {
|
|||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// VEKTOR-BASEMAP (protomaps-leaflet + eigene PMTiles) — lazy laden
|
||||
// MapLibre-GL für Seitenkarten (UI.map) — lazy laden + Facade
|
||||
// ----------------------------------------------------------
|
||||
let _uiGL = false; // ist die aktuell erstellte UI-Karte GL?
|
||||
let _maplibreUIPromise = null;
|
||||
|
||||
// Gleiche Logik wie pages/map.js _useGL: Staging-Default AN, Prod AUS, by_map_gl überschreibt.
|
||||
function _uiUseGL() {
|
||||
try {
|
||||
const flag = localStorage.getItem('by_map_gl');
|
||||
if (flag === '1') return true;
|
||||
if (flag === '0') return false;
|
||||
return /(^|\.)staging\.banyaro\.app$/.test(location.hostname);
|
||||
} catch (e) { return false; }
|
||||
}
|
||||
|
||||
function loadMapLibreUI() {
|
||||
if (_maplibreUIPromise) return _maplibreUIPromise;
|
||||
const v = '?v=' + (window.APP_VER || '');
|
||||
if (!document.querySelector('link[href*="maplibre-gl.css"]')) {
|
||||
const l = document.createElement('link');
|
||||
l.rel = 'stylesheet'; l.href = '/js/vendor/maplibre-gl.css';
|
||||
document.head.appendChild(l);
|
||||
}
|
||||
const seq = (srcs) => srcs.reduce((p, src) => p.then(() => new Promise((res, rej) => {
|
||||
if ((src.includes('maplibre-gl.js') && window.maplibregl) ||
|
||||
(src.includes('pmtiles.js') && window.pmtiles) ||
|
||||
(src.includes('map-gl-style') && window.MapGLStyle) ||
|
||||
(src.includes('map-gl-mini') && window.MapGLMini)) return res();
|
||||
const s = document.createElement('script');
|
||||
s.src = src + v; s.onload = res; s.onerror = rej;
|
||||
document.head.appendChild(s);
|
||||
})), Promise.resolve());
|
||||
_maplibreUIPromise = seq(['/js/vendor/maplibre-gl.js', '/js/vendor/pmtiles.js', '/js/map-gl-style.js', '/js/map-gl-mini.js']).then(() => {
|
||||
if (!(window.maplibregl && window.pmtiles && window.MapGLStyle && window.MapGLMini)) throw new Error('MapLibre (UI) nicht geladen');
|
||||
try { const proto = new pmtiles.Protocol(); maplibregl.addProtocol('pmtiles', proto.tile); } catch (e) { /* evtl. schon registriert */ }
|
||||
});
|
||||
return _maplibreUIPromise;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// VEKTOR-BASEMAP (protomaps-leaflet + eigene PMTiles) — lazy laden [DEAKTIVIERT]
|
||||
// ----------------------------------------------------------
|
||||
let _protomapsPromise = null;
|
||||
function loadProtomaps() {
|
||||
|
|
@ -905,9 +972,10 @@ const UI = (() => {
|
|||
// ----------------------------------------------------------
|
||||
function leafletMarker({ lat, lon, color = 'var(--c-primary)', icon = '', size = 32, label = '' } = {}) {
|
||||
const inner = label || icon;
|
||||
const html = `<div style="background:${color};color:#fff;font-size:${Math.round(size * 0.45)}px;font-weight:700;width:${size}px;height:${size}px;border-radius:50%;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 5px rgba(0,0,0,0.3);border:2px solid rgba(255,255,255,0.8)">${inner}</div>`;
|
||||
if (_uiGL && window.MapGLMini) return MapGLMini.svgMarker(lat, lon, html, { size, anchorY: size / 2 });
|
||||
const divIcon = L.divIcon({
|
||||
className: '',
|
||||
html: `<div style="background:${color};color:#fff;font-size:${Math.round(size * 0.45)}px;font-weight:700;width:${size}px;height:${size}px;border-radius:50%;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 5px rgba(0,0,0,0.3);border:2px solid rgba(255,255,255,0.8)">${inner}</div>`,
|
||||
className: '', html,
|
||||
iconSize: [size, size],
|
||||
iconAnchor: [size / 2, size / 2],
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue