Sprint D: Karten-Familie auf UI.map.create+svgMarker konsolidiert, SW by-v1107

Neue zentrale Helper (in Sprint B vorbereitet) jetzt von 5 Seiten genutzt:

walks.js (1 Karten-Init):
- L.map+L.tileLayer → await UI.map.create('walks-map', {...})
- _initMap zu async, Aufrufer in _switchView und _loadData angepasst
- Mini-Karte im Walk-Formular (Modal) bleibt unverändert
  (braucht eigene dragging/scrollWheelZoom-Options)
- view-toggle nicht migriert (responsive CSS-Konflikt mit Desktop)

poison.js (1 Karten-Init):
- L.map+L.tileLayer → await UI.map.create('poison-map', {...})
- _initMap zu async, manueller UI.loadLeaflet entfernt
- DangerCircle + User-Marker unverändert

events.js (1 Karten-Init + Diamant-Marker):
- await UI.map.create('ev-map', {...})
- Rotierter Diamant: L.divIcon+L.marker → UI.map.svgMarker
  (HTML 1:1 erhalten)

lost.js (1 Karten-Init + Puls-Marker):
- Eigene async _loadLeaflet() Funktion komplett entfernt — UI.map.create
  übernimmt das jetzt zentral
- await UI.map.create('lost-map', {...})
- Puls-Animation 🐕: L.divIcon+L.marker → UI.map.svgMarker
- _initMap zu async

routes.js (6 von 7 Karten-Inits):
- _suggestMap, _recMap, _searchMap, _navMap, trimMap, _buildDetailMap
  alle auf UI.map.create umgestellt + zu async
- _buildMiniMap (Route-Card-Preview) bleibt unverändert
  (braucht 6 spezifische Interaction-Disable Options)
- View-Toggle auf neue .map-list-toggle Klasse umgestellt
  (Border-Inline-Styles raus)

NEUE CSS-KLASSE in components.css:
- .map-list-toggle (vereinheitlichter Karten/Listen-Umschalter)
- Verwendet von routes.js; walks/events können später folgen

Tests 19/19 grün. GPS-Tracking-Logik (Polylines, Recording, Trim)
komplett unangetastet. Marker-Cluster-Logik unverändert.
This commit is contained in:
rene 2026-05-27 08:17:06 +02:00
parent c8ef4939f1
commit 73872e2c21
11 changed files with 130 additions and 152 deletions

View file

@ -130,54 +130,24 @@ window.Page_lost = (() => {
document.getElementById('lost-btn-report')
?.addEventListener('click', _showReportForm);
await _loadLeaflet();
_initMap();
await _initMap();
setTimeout(() => _map?.invalidateSize(), 100);
await _locateAndLoad();
}
// ----------------------------------------------------------
// LEAFLET DYNAMISCH LADEN
// KARTE INITIALISIEREN (lädt Leaflet via UI.map.create)
// ----------------------------------------------------------
async function _loadLeaflet() {
if (_leafletLoaded || window.L) { _leafletLoaded = true; return; }
await new Promise(resolve => {
if (document.querySelector('link[href*="leaflet"]')) { resolve(); return; }
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = '/css/leaflet.css';
link.onload = resolve;
link.onerror = resolve;
document.head.appendChild(link);
});
await new Promise((resolve, reject) => {
if (document.querySelector('script[src*="leaflet"]')) { resolve(); return; }
const s = document.createElement('script');
s.src = '/js/leaflet.js';
s.onload = resolve;
s.onerror = reject;
document.head.appendChild(s);
});
_leafletLoaded = true;
}
// ----------------------------------------------------------
// KARTE INITIALISIEREN
// ----------------------------------------------------------
function _initMap() {
async function _initMap() {
_injectStyles();
const mapEl = document.getElementById('lost-map');
if (!mapEl || !window.L || _map) return;
if (!mapEl || _map) return;
_map = L.map('lost-map', { zoomControl: true, attributionControl: false })
.setView([51.1657, 10.4515], 6);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
}).addTo(_map);
_map = await UI.map.create('lost-map', {
center: [51.1657, 10.4515], zoom: 6,
zoomControl: true, attributionControl: false,
});
_leafletLoaded = true;
}
// ----------------------------------------------------------
@ -303,22 +273,17 @@ window.Page_lost = (() => {
_reports.forEach(r => {
const dotColor = r._isPending ? '#d97706' : '#e74c3c';
const anim = r._isPending ? 'by-lost-pulse-p' : 'by-lost-pulse-r';
const icon = L.divIcon({
className : '',
html : `<div style="background:${dotColor};color:#fff;border-radius:50%;
const html = `<div style="background:${dotColor};color:#fff;border-radius:50%;
width:34px;height:34px;
display:flex;align-items:center;justify-content:center;
font-size:17px;border:2px solid #fff;
animation:${anim} 1.8s ease-in-out infinite">🐕</div>`,
iconSize : [34, 34],
iconAnchor : [17, 17],
});
animation:${anim} 1.8s ease-in-out infinite">🐕</div>`;
const distStr = r.distanz_m !== undefined
? (r.distanz_m < 1000 ? `${Math.round(r.distanz_m)} m` : `${(r.distanz_m / 1000).toFixed(1)} km`)
: '';
const marker = L.marker([r.lat, r.lon], { icon })
const marker = UI.map.svgMarker(r.lat, r.lon, html, { size: 34, anchorY: 17 })
.addTo(_map)
.bindPopup(`
<b>🔍 ${_escape(r.name)}</b><br>