import L from "leaflet"; export class OverlappingMarkerSpiderfier { constructor(map, options = {}) { this.map = map; this.markers = []; this.markerListeners = []; this.keepSpiderfied = options.keepSpiderfied || false; // Basiseinstellungen für die Distanz und die Zoomstufenabhängigkeit this.baseNearbyDistance = options.nearbyDistance || 20; this.nearbyDistance = this.baseNearbyDistance; // Initialwert setzen this.circleSpiralSwitchover = options.circleSpiralSwitchover || 9; this.circleFootSeparation = options.circleFootSeparation || 25; this.circleStartAngle = options.circleStartAngle || Math.PI / 6; this.spiralFootSeparation = options.spiralFootSeparation || 28; this.spiralLengthStart = options.spiralLengthStart || 11; this.spiralLengthFactor = options.spiralLengthFactor || 5; this.legWeight = options.legWeight || 1.5; this.legColors = options.legColors || { usual: "#222", highlighted: "#f00", }; this.initMarkerArrays(); this.map.on("click", () => this.unspiderfy()); this.map.on("zoomend", () => this.unspiderfy()); } initMarkerArrays() { this.markers = []; this.markerListeners = []; } addMarker(marker) { if (!marker._oms) { marker._oms = {}; // Stellt sicher, dass _oms ein Objekt ist } const listener = () => { this.spiderListener(marker); }; marker.on("click", listener); this.markerListeners.push(listener); this.markers.push(marker); return this; } spiderListener(marker) { const spidered = marker._oms.spidered; if (!spidered) { const nearMarkers = this.nearbyMarkers(marker); if (nearMarkers.length > 1) { this.spiderfy(nearMarkers); } } else { this.unspiderfy(); // Schließt alle gespiderfied Marker, wenn einer erneut geklickt wird } } nearbyMarkers(marker) { return this.markers.filter((m) => { const distance = this.map.distance(marker.getLatLng(), m.getLatLng()); return distance < this.nearbyDistance && marker !== m; }); } //--------------------------------------------------------------------------------------------- spiderfy(markers) { const centerPt = this.map.latLngToLayerPoint(markers[0].getLatLng()); markers.forEach((marker, i) => { const angle = this.circleStartAngle + (i * 2 * Math.PI) / markers.length; const legLength = this.circleFootSeparation * (2 + i / markers.length); const newPt = L.point(centerPt.x + legLength * Math.cos(angle), centerPt.y + legLength * Math.sin(angle)); const newLatLng = this.map.layerPointToLatLng(newPt); if (!marker._oms) { marker._oms = {}; } marker._oms.usualPosition = marker.getLatLng(); marker._oms.spidered = true; // Zeichne eine Linie zwischen ursprünglicher und neuer Position const leg = L.polyline([marker._oms.usualPosition, newLatLng], { color: this.legColors.usual, weight: this.legWeight, }).addTo(this.map); marker._oms.leg = leg; // Speichert die Linie im Marker-Objekt marker.setLatLng(newLatLng); marker.setZIndexOffset(1000); }); } //--------------------------------------------------------------------------------------------- unspiderfy() { this.markers.forEach((marker) => { if (marker._oms && marker._oms.spidered) { // Falls eine Linie existiert, entferne sie aus der Karte if (marker._oms.leg) { this.map.removeLayer(marker._oms.leg); marker._oms.leg = null; } marker.setLatLng(marker._oms.usualPosition); marker.setZIndexOffset(0); marker._oms.spidered = false; } }); // 🔥 Künstliches Click-Event auslösen, um die UI zu aktualisieren setTimeout(() => { this.map.fire("click"); console.log("Click-Event ausgelöst in OverlappingMarkerspiderfier.js in unspiderfy "); }, 10); // Kurze Verzögerung, um sicherzustellen, dass die UI neu gerendert wird } //--------------------------------------------------------------------------------------------- }