Files
nodeMap/utils/initializeMap.js
2025-09-16 11:55:41 +02:00

163 lines
4.9 KiB
JavaScript

// utils/initializeMap.js
import L from "leaflet";
import "leaflet-contextmenu";
import "leaflet/dist/leaflet.css";
import "leaflet-contextmenu/dist/leaflet.contextmenu.css";
import "overlapping-marker-spiderfier-leaflet";
export const initializeMap = (
mapContainer,
setMenuItemAdded,
addItemsToMapContextMenu,
hasRights,
setPolylineEventsDisabled,
logError = false
) => {
// basePath wird aus config.json geladen (siehe unten)
let basePath = undefined;
if (
!mapContainer ||
!(mapContainer instanceof HTMLElement) ||
!document.body.contains(mapContainer)
) {
if (logError) {
console.error("❌ Fehler: map container ist nicht definiert oder nicht im DOM.");
}
return null;
}
// Robuste Entfernung einer evtl. alten Leaflet-Instanz und Reset des DOM-Elements
if (mapContainer) {
if (mapContainer._leaflet_id) {
try {
// Leaflet-Instanz entfernen
if (mapContainer._leaflet_map && typeof mapContainer._leaflet_map.remove === "function") {
mapContainer._leaflet_map.remove();
}
// Leaflet 1.7+ speichert die Map-Instanz in L.Map._instances
if (L && L.Map && L.Map._instances && mapContainer._leaflet_id) {
delete L.Map._instances[mapContainer._leaflet_id];
}
// Auch in L.DomUtil._store ggf. entfernen
if (L && L.DomUtil && L.DomUtil._store && mapContainer._leaflet_id) {
delete L.DomUtil._store[mapContainer._leaflet_id];
}
// _leaflet_id vom DOM-Element entfernen
delete mapContainer._leaflet_id;
// Alle weiteren _leaflet-Properties entfernen
for (const key in mapContainer) {
if (key.startsWith("_leaflet")) {
try {
delete mapContainer[key];
} catch (e) {}
}
}
} catch (e) {
console.warn("Fehler beim Entfernen der alten Leaflet-Instanz:", e);
}
}
// Container leeren (immer, auch wenn keine Map-Instanz)
mapContainer.innerHTML = "";
}
// --- CONFIG LOADING ---
let config = null;
let tileLayerUrl = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png";
let mapCenter = [53.111111, 8.4625];
let mapZoom = 12;
let minZoom = 5;
let maxZoom = 20;
try {
if (window && window.__leafletConfig) {
config = window.__leafletConfig;
} else {
const xhr = new XMLHttpRequest();
xhr.open("GET", "/config.json", false); // false = synchronous
xhr.send(null);
if (xhr.status === 200) {
config = JSON.parse(xhr.responseText);
window.__leafletConfig = config;
}
}
if (config) {
// basePath aus config.json
if (typeof config.basePath === "string") {
basePath = config.basePath;
}
// Tile source
if (config.tileSources && config.active && config.tileSources[config.active]) {
const tileSource = config.tileSources[config.active];
tileLayerUrl = tileSource.url || tileLayerUrl;
// Dynamische URL für Server-Tiles
if (tileLayerUrl.startsWith("/tiles") || tileLayerUrl.startsWith("tiles")) {
tileLayerUrl = `${window.location.origin.replace(/\/$/, "")}${
tileLayerUrl.startsWith("/") ? tileLayerUrl : "/" + tileLayerUrl
}`;
}
minZoom = tileSource.minZoom ?? minZoom;
maxZoom = tileSource.maxZoom ?? maxZoom;
}
// Center
if (Array.isArray(config.center)) {
mapCenter = config.center;
}
// Zoom (optional, fallback to 12)
if (typeof config.zoom === "number") {
mapZoom = config.zoom;
}
// minZoom/maxZoom global fallback
if (typeof config.minZoom === "number") {
minZoom = config.minZoom;
}
if (typeof config.maxZoom === "number") {
maxZoom = config.maxZoom;
}
}
} catch (e) {
// Fallback bleibt OSM und Defaults
}
let initMap;
try {
initMap = L.map(mapContainer, {
center: mapCenter,
zoom: mapZoom,
minZoom: minZoom,
maxZoom: maxZoom,
zoomControl: false,
dragging: true,
contextmenu: true,
layers: [],
});
} catch (e) {
if (e.message && e.message.includes("Map container is already initialized")) {
console.warn(
"Leaflet: Map container is already initialized. Map wird nicht erneut initialisiert."
);
return;
}
throw e;
}
initMap.dragging.enable();
L.tileLayer(tileLayerUrl, {
attribution: "© OpenStreetMap contributors",
tileSize: 256,
minZoom: minZoom,
maxZoom: maxZoom,
noWrap: true,
errorTileUrl: "/img/empty-tile.png", // Optional
}).addTo(initMap);
const overlappingMarkerSpiderfier = new OverlappingMarkerSpiderfier(initMap, {
nearbyDistance: 20,
});
if (typeof addItemsToMapContextMenu === "function") {
addItemsToMapContextMenu(initMap, setMenuItemAdded, setPolylineEventsDisabled);
}
return { map: initMap, oms: overlappingMarkerSpiderfier };
};