166 lines
5.1 KiB
JavaScript
166 lines
5.1 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,
|
|
// Disable default position; we'll add our own control at bottom-right
|
|
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();
|
|
|
|
// Do not add the default Leaflet zoom control; we'll render custom React controls in MapComponent
|
|
|
|
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 };
|
|
};
|