react-leaflet-cluster
Version:
React-leaflet-cluster is a plugin for react-leaflet. A wrapper component of Leaflet.markercluster.
110 lines (109 loc) • 3.74 kB
JavaScript
// src/index.tsx
import {
extendContext,
createElementObject,
createPathComponent
} from "@react-leaflet/core";
import L from "leaflet";
import "leaflet.markercluster";
function getPropsAndEvents(props) {
let clusterProps = {};
let clusterEvents = {};
const { children, ...rest } = props;
Object.entries(rest).forEach(([propName, prop]) => {
if (propName.startsWith("on")) {
clusterEvents = { ...clusterEvents, [propName]: prop };
} else {
clusterProps = { ...clusterProps, [propName]: prop };
}
});
return { clusterProps, clusterEvents };
}
function createMarkerClusterGroup(props, context) {
const { clusterProps, clusterEvents } = getPropsAndEvents(props);
const markerClusterGroup = new L.MarkerClusterGroup(clusterProps);
Object.entries(clusterEvents).forEach(([eventAsProp, callback]) => {
const clusterEvent = `cluster${eventAsProp.substring(2).toLowerCase()}`;
markerClusterGroup.on(clusterEvent, callback);
});
const proto = L.MarkerClusterGroup.prototype;
let addBuffer = [];
let removeBuffer = [];
let flushScheduled = false;
function flush() {
flushScheduled = false;
const netOps = /* @__PURE__ */ new Map();
for (const l of addBuffer) netOps.set(l, (netOps.get(l) ?? 0) + 1);
for (const l of removeBuffer) netOps.set(l, (netOps.get(l) ?? 0) - 1);
const toAdd = [];
const toRemove = [];
for (const [layer, count] of netOps) {
if (count > 0) toAdd.push(layer);
else if (count < 0) toRemove.push(layer);
}
removeBuffer = [];
addBuffer = [];
if (toRemove.length > 0) markerClusterGroup.removeLayers(toRemove);
if (toAdd.length > 0) markerClusterGroup.addLayers(toAdd);
}
function scheduleFlush() {
if (flushScheduled) return;
flushScheduled = true;
queueMicrotask(flush);
}
markerClusterGroup.addLayer = function(layer) {
if (!this._map) return proto.addLayer.call(this, layer);
addBuffer.push(layer);
scheduleFlush();
return this;
};
markerClusterGroup.removeLayer = function(layer) {
if (!this._map) return proto.removeLayer.call(this, layer);
removeBuffer.push(layer);
scheduleFlush();
return this;
};
const originalClearLayers = markerClusterGroup.clearLayers;
markerClusterGroup.clearLayers = function() {
addBuffer = [];
removeBuffer = [];
flushScheduled = false;
return originalClearLayers.call(this);
};
markerClusterGroup._moveChild = function(layer, from, to) {
;
layer._latlng = from;
proto.removeLayer.call(this, layer);
layer._latlng = to;
proto.addLayer.call(this, layer);
};
return createElementObject(
markerClusterGroup,
extendContext(context, { layerContainer: markerClusterGroup })
);
}
var updateMarkerCluster = (instance, props, prevProps) => {
const { clusterProps, clusterEvents } = getPropsAndEvents(props);
const { clusterProps: prevClusterProps, clusterEvents: prevClusterEvents } = getPropsAndEvents(prevProps);
Object.keys(clusterProps).forEach((key) => {
if (clusterProps[key] !== prevClusterProps[key]) {
instance.options[key] = clusterProps[key];
}
});
Object.entries(prevClusterEvents).forEach(([eventAsProp, callback]) => {
const clusterEvent = `cluster${eventAsProp.substring(2).toLowerCase()}`;
instance.off(clusterEvent, callback);
});
Object.entries(clusterEvents).forEach(([eventAsProp, callback]) => {
const clusterEvent = `cluster${eventAsProp.substring(2).toLowerCase()}`;
instance.on(clusterEvent, callback);
});
};
var MarkerClusterGroup = createPathComponent(
createMarkerClusterGroup,
updateMarkerCluster
);
var index_default = MarkerClusterGroup;
export {
index_default as default
};