"Overlapping Marker Spiderfier for Leaflet"Bibliothek in ein ES Module umwandeln
This commit is contained in:
113
lib/OverlappingMarkerSpiderfier.js
Normal file
113
lib/OverlappingMarkerSpiderfier.js
Normal file
@@ -0,0 +1,113 @@
|
||||
import L from "leaflet";
|
||||
|
||||
export class OverlappingMarkerSpiderfier {
|
||||
constructor(map, options = {}) {
|
||||
this.map = map;
|
||||
this.markers = [];
|
||||
this.markerListeners = [];
|
||||
this.listeners = {};
|
||||
this.nearbyDistance = options.nearbyDistance || 20;
|
||||
this.circleSpiralSwitchover = options.circleSpiralSwitchover || 9;
|
||||
this.circleFootSeparation = options.circleFootSeparation || 25; // pixels
|
||||
this.circleStartAngle = options.circleStartAngle || Math.PI / 6;
|
||||
this.spiralFootSeparation = options.spiralFootSeparation || 28; // pixels
|
||||
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.bind(this));
|
||||
this.map.on("zoomend", this.unspiderfy.bind(this));
|
||||
}
|
||||
|
||||
initMarkerArrays() {
|
||||
this.markers = [];
|
||||
this.markerListeners = [];
|
||||
}
|
||||
|
||||
addMarker(marker) {
|
||||
if (marker._oms) return this;
|
||||
marker._oms = true;
|
||||
|
||||
const listener = () => {
|
||||
this.spiderListener(marker);
|
||||
};
|
||||
|
||||
marker.on("click", listener);
|
||||
this.markerListeners.push(listener);
|
||||
this.markers.push(marker);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
spiderListener(marker) {
|
||||
const spidered = !!marker._omsData;
|
||||
if (!spidered) {
|
||||
const nearMarkers = this.nearbyMarkers(marker);
|
||||
if (nearMarkers.length > 1) {
|
||||
this.spiderfy(nearMarkers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nearbyMarkers(marker) {
|
||||
const nearby = [];
|
||||
const markerPt = this.map.latLngToLayerPoint(marker.getLatLng());
|
||||
this.markers.forEach((m) => {
|
||||
if (m !== marker) {
|
||||
const mPt = this.map.latLngToLayerPoint(m.getLatLng());
|
||||
const distanceSq = this.ptDistanceSq(mPt, markerPt);
|
||||
if (distanceSq < this.nearbyDistance * this.nearbyDistance) {
|
||||
nearby.push(m);
|
||||
}
|
||||
}
|
||||
});
|
||||
return nearby;
|
||||
}
|
||||
|
||||
spiderfy(markers) {
|
||||
const centerPt = this.map.latLngToLayerPoint(markers[0].getLatLng());
|
||||
markers.forEach((marker, index) => {
|
||||
const angle =
|
||||
this.circleStartAngle + (index * 2 * Math.PI) / markers.length;
|
||||
const legLength =
|
||||
this.circleFootSeparation * (2 + index / markers.length);
|
||||
const newPt = L.point(
|
||||
centerPt.x + legLength * Math.cos(angle),
|
||||
centerPt.y + legLength * Math.sin(angle)
|
||||
);
|
||||
|
||||
const newLatLng = this.map.layerPointToLatLng(newPt);
|
||||
marker.setLatLng(newLatLng);
|
||||
marker.setZIndexOffset(1000);
|
||||
|
||||
const polyline = L.polyline([marker.getLatLng(), newLatLng], {
|
||||
color: this.legColors.usual,
|
||||
weight: this.legWeight,
|
||||
clickable: false,
|
||||
});
|
||||
this.map.addLayer(polyline);
|
||||
});
|
||||
}
|
||||
|
||||
unspiderfy() {
|
||||
this.markers.forEach((marker) => {
|
||||
if (marker._omsData) {
|
||||
marker.setLatLng(marker._omsData.usualPosition);
|
||||
marker.setZIndexOffset(0);
|
||||
this.map.removeLayer(marker._omsData.leg);
|
||||
delete marker._omsData;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ptDistanceSq(pt1, pt2) {
|
||||
const dx = pt1.x - pt2.x;
|
||||
const dy = pt1.y - pt2.y;
|
||||
return dx * dx + dy * dy;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user