Add files via upload

This commit is contained in:
Serverlele30 authored and GitHub committed 2026-08-31 10:11:52 +02:00
1 parent 63da9cdbba
commit e53cd580c5
4 files changed
+274 -19

No files matched your search

+56 -7
View File
@@ -20,6 +20,7 @@ const LiveMap = (() => {
let radarPollHandle = null;
let tripPollHandle = null;
let currentTripId = null;
let isolatedMarker = null; // persistenter Marker im Isolations-Modus, wird nur aktualisiert statt neu erzeugt
let isolatedVehicleMeta = null; // { line, color, textColor } für die Banner-Anzeige
let getModesParam = () => null; // wird von außen (ModeFilter) gesetzt
@@ -59,6 +60,11 @@ const LiveMap = (() => {
return geojson.features.map((f) => [f.geometry.coordinates[1], f.geometry.coordinates[0]]);
}
function vehiclePopupHtml(v) {
return `<strong>${v.line || 'Linie unbekannt'}</strong><br>${v.direction || ''}<br>` +
`<small>Nächster Halt: ${v.nextStopover || '–'}</small>`;
}
// ---------- Radar-Modus (Standard: alle Fahrzeuge im Ausschnitt) ----------
async function refreshRadar() {
@@ -130,22 +136,58 @@ const LiveMap = (() => {
return;
}
radarLayer.clearLayers();
const v = data.vehicles[0];
if (v && v.latitude != null && v.longitude != null) {
const marker = L.marker([v.latitude, v.longitude], { icon: vehicleIcon(v.line, v.color, v.textColor) });
marker.bindPopup(`<strong>${v.line || ''}</strong><br>${v.direction || ''}<br><small>Nächster Halt: ${v.nextStopover || '–'}</small>`);
marker.addTo(radarLayer);
if (!v || v.latitude == null || v.longitude == null) {
// Fahrzeug gerade nicht meldend (z.B. kurzzeitig aus der Live-Erfassung) -
// Marker stehen lassen statt zu entfernen, nächster Poll aktualisiert ihn wieder.
return;
}
// WICHTIG: Marker wird wiederverwendet statt bei jedem Poll neu erzeugt zu
// werden. Vorher wurde hier radarLayer.clearLayers() + ein komplett neuer
// Marker angelegt - das hat ein ggf. geöffnetes Popup jedes Mal geschlossen,
// sodass die Fahrzeuginfo (Richtung, nächster Halt) nach dem ersten Klick nie
// wieder aktualisiert im UI sichtbar wurde.
if (isolatedMarker) {
isolatedMarker.setLatLng([v.latitude, v.longitude]);
isolatedMarker.setIcon(vehicleIcon(v.line, v.color, v.textColor));
isolatedMarker.setPopupContent(vehiclePopupHtml(v));
} else {
isolatedMarker = L.marker([v.latitude, v.longitude], { icon: vehicleIcon(v.line, v.color, v.textColor) });
isolatedMarker.bindPopup(vehiclePopupHtml(v));
isolatedMarker.addTo(radarLayer);
}
isolatedVehicleMeta = { line: v.line, color: v.color, textColor: v.textColor };
updateIsolationBanner();
}
async function isolateVehicle(vehicle) {
if (!vehicle || !vehicle.tripId) return;
// Das ursprüngliche Leaflet-Popup des angeklickten Radar-Markers (aus
// bindPopup in refreshRadar) schließen, bevor wir in den Isolations-Modus
// wechseln - sonst blitzt es kurz auf und verschwindet dann kommentarlos.
map.closePopup();
setMode('isolated');
currentTripId = vehicle.tripId;
isolatedMarker = null;
radarLayer.clearLayers();
isolatedVehicleMeta = { line: vehicle.line, color: vehicle.color, textColor: vehicle.textColor };
updateIsolationBanner();
// Sofort einen Marker mit den Daten aus dem Klick anzeigen (nicht erst auf
// den ersten Poll warten) und direkt öffnen, damit man die Fahrzeuginfo
// ohne weiteren Klick sieht.
isolatedMarker = L.marker([vehicle.latitude, vehicle.longitude], {
icon: vehicleIcon(vehicle.line, vehicle.color, vehicle.textColor),
});
isolatedMarker.bindPopup(vehiclePopupHtml(vehicle));
isolatedMarker.addTo(radarLayer);
isolatedMarker.openPopup();
routeLayer.clearLayers();
try {
const trip = await API.getTrip(vehicle.tripId, { polyline: true });
@@ -159,13 +201,13 @@ const LiveMap = (() => {
console.error('Trip-Polyline-Fehler:', err.message);
}
refreshIsolated();
if (radarPollHandle) clearInterval(radarPollHandle);
radarPollHandle = setInterval(refreshIsolated, 10000);
}
function clearIsolation() {
currentTripId = null;
isolatedMarker = null;
isolatedVehicleMeta = null;
updateIsolationBanner();
startRadar();
@@ -211,12 +253,19 @@ const LiveMap = (() => {
if (data.currentLocation) {
const pos = [data.currentLocation.latitude, data.currentLocation.longitude];
const popupHtml = `<strong>${data.line || ''}</strong><br>→ ${data.direction || ''}`;
if (tripMarker) {
tripMarker.setLatLng(pos);
tripMarker.setIcon(vehicleIcon(data.line, data.color, data.textColor));
// setPopupContent statt erneutem bindPopup, sonst schließt sich ein
// gerade geöffnetes Popup bei jedem Poll wieder (gleicher Fehler wie
// im Isolations-Modus).
if (tripMarker.getPopup()) tripMarker.setPopupContent(popupHtml);
else tripMarker.bindPopup(popupHtml);
} else {
tripMarker = L.marker(pos, { icon: vehicleIcon(data.line, data.color, data.textColor) }).addTo(routeLayer);
tripMarker.bindPopup(popupHtml);
}
tripMarker.bindPopup(`<strong>${data.line || ''}</strong><br>→ ${data.direction || ''}`);
}
}