implement marker clusters
This commit is contained in:
@@ -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='© <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>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user