implement marker clusters

This commit is contained in:
Matteo Rosati
2026-01-18 00:09:18 +01:00
parent 6df84ac67e
commit c351da70b2
3 changed files with 61 additions and 1 deletions

View File

@@ -1,6 +1,9 @@
import { MapContainer, TileLayer, Marker, Popup } from "react-leaflet";
import MarkerClusterGroup from "react-leaflet-cluster";
import L from "leaflet";
import "leaflet/dist/leaflet.css";
import "leaflet.markercluster/dist/MarkerCluster.css";
import "leaflet.markercluster/dist/MarkerCluster.Default.css";
import type { Plext } from "../types";
// Fix Leaflet marker icons
@@ -15,6 +18,39 @@ interface PlayerMapProps {
plexts: Plext[];
}
/**
* Creates a custom cluster icon with the number of markers
* @param cluster - The cluster object from leaflet.markercluster
* @returns A Leaflet DivIcon with the cluster count
*/
const createClusterIcon = (cluster: any): L.DivIcon => {
const count = cluster.getChildCount();
let size = 40;
if (count > 10) size = 50;
if (count > 50) size = 60;
if (count > 100) size = 70;
return new L.DivIcon({
html: `<div style="
background-color: #666;
color: white;
border-radius: 50%;
width: ${size}px;
height: ${size}px;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-size: ${size / 2}px;
border: 2px solid white;
box-shadow: 0 2px 5px rgba(0,0,0,0.3);
">${count}</div>`,
className: "custom-cluster-icon",
iconSize: [size, size],
iconAnchor: [size / 2, size / 2],
});
};
export function PlayerMap({ plexts }: PlayerMapProps) {
// Get player locations from plexts
const playerLocations = plexts
@@ -45,7 +81,18 @@ export function PlayerMap({ plexts }: PlayerMapProps) {
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
{playerLocations.map((location, index) => {
<MarkerClusterGroup
chunkedLoading
maxClusterRadius={60}
spiderfyOnMaxZoom={true}
showCoverageOnHover={false}
zoomToBoundsOnClick={true}
removeOutsideVisibleBounds={true}
animate={true}
animateAddingMarkers={true}
iconCreateFunction={createClusterIcon}
>
{playerLocations.map((location, index) => {
if (!location) return null;
const markerColor = location.team === "RESISTANCE" ? "blue" : "green";
@@ -76,6 +123,7 @@ export function PlayerMap({ plexts }: PlayerMapProps) {
</Marker>
);
})}
</MarkerClusterGroup>
</MapContainer>
</div>
);