Files
irth-new-client-120/src/components/google-map/GoogleMapMarkers.tsx
T

100 lines
2.6 KiB
TypeScript

import { useMap } from "@vis.gl/react-google-maps";
import { useEffect, useRef, useState } from "react";
import IGMapPoi from "../../types/IGMapPoi";
import MapMarker from "./MapMarker";
import {
MarkerClusterer,
DefaultRenderer,
Cluster,
Marker,
} from "@googlemaps/markerclusterer";
class CustomMarkerRenderer extends DefaultRenderer {
render({
count,
position,
}: Cluster): google.maps.marker.AdvancedMarkerElement {
const svgElement = document.createElement("div");
svgElement.innerHTML = `
<svg fill="white" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 240" width="50" height="50">
<circle cx="120" cy="120" opacity="1" r="70" />
</svg>
<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: black; font-size: 12px; font-weight: bold;">
${count}
</div>`;
const marker = new google.maps.marker.AdvancedMarkerElement({
position,
content: svgElement,
zIndex: Math.max(1000, count),
});
return marker;
}
}
export default function GoogleMapMarkers({
data,
filter,
}: {
data: IGMapPoi[];
filter: string;
}) {
const map = useMap();
const [markers, setMarkers] = useState<{ [key: string]: Marker }>({});
const [selectedMarker, setSelectedMarker] = useState<number | null>(null);
const clusterer = useRef<MarkerClusterer | null>(null);
useEffect(() => {
if (!map) return;
if (!clusterer.current) {
clusterer.current = new MarkerClusterer({
map: map,
renderer: new CustomMarkerRenderer(),
});
}
}, [map]);
useEffect(() => {
clusterer.current?.clearMarkers();
clusterer.current?.addMarkers(Object.values(markers));
}, [markers]);
const setMarkerRef = (marker: Marker | null, key: string) => {
if (marker && markers[key]) return;
if (!marker && !markers[key]) return;
setMarkers((prev) => {
if (prev[key] === marker) return prev;
if (marker) {
return { ...prev, [key]: marker };
} else {
const newMarkers = { ...prev };
delete newMarkers[key];
return newMarkers;
}
});
};
return (
<>
{data.map(
(poi: IGMapPoi, index: number) =>
(filter === poi.type || filter === "All") && (
<MapMarker
key={index}
markerKey={index}
poi={poi}
setMarkerRef={setMarkerRef}
isSelected={selectedMarker === index}
setSelectedMarker={setSelectedMarker}
>
{poi.customMarker}
</MapMarker>
)
)}
</>
);
}