我第一次在 React 应用程序中使用 googlemaps,遵循此处的 google 文档:https://developers.google.com/codelabs/maps-platform/maps-platform-101-react-js#0 .
这是一个基本的应用程序,它只是在地图上显示一组坐标的标记图钉,这些坐标全部位于英国境内。这工作正常,直到使用大量数据 - 我必须显示大约 20k-25k 标记。
我正在使用集群,也按照上面的文档。
整个过程持续了大约一分钟,其中浏览器速度非常慢并且经常冻结。我将分享下面的代码,但这几乎是文档中内容的抄本。我愿意以更小的“块”的形式加载数据,比如每隔几秒加载 3000 个引脚,尽管我无法根据文档建议的代码让它工作。
我正在运行节点版本 22.11.0。
任何人都可以帮忙解释为什么这么慢以及改进的方法吗?如果有人能帮忙的话,我很乐意为“请我喝杯咖啡”链接做出贡献。
这是主地图组件:
import { APIProvider, Map } from "@vis.gl/react-google-maps";
import { IMapProps } from "../types";
import MapMarker from "./MapMarker";
const { VITE_GOOGLE_MAPS_API_KEY } = import.meta.env;
const MyMap: React.FC<IMapProps> = ({ mapData }) => {
return (
<APIProvider
apiKey={VITE_GOOGLE_MAPS_API_KEY}
>
<div className="w-full relative map-height">
<Map
defaultCenter={{ lat: 54.5, lng: -2.0 }}
defaultZoom={6.3}
mapId={"639b81a18b67be98"}
>
<MapMarker mapData={mapData} />
</Map>
</div>
</APIProvider>
);
};
export default MyMap;
以及标记代码:
import { useState, useRef, useEffect } from "react";
import { IFormattedData, IMapMarkerProps } from "../types";
import { useMap, AdvancedMarker, Pin } from "@vis.gl/react-google-maps";
import { MarkerClusterer } from "@googlemaps/markerclusterer";
import type { Marker } from "@googlemaps/markerclusterer";
const MapMarker: React.FC<IMapMarkerProps> = ({ mapData }) => {
const map = useMap();
const [markers, setMarkers] = useState<{ [key: string]: Marker }>({});
const clusterer = useRef<MarkerClusterer | null>(null);
useEffect(() => {
if (!map) return;
if (!clusterer.current) {
clusterer.current = new MarkerClusterer({ map });
}
}, [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 (marker) {
return { ...prev, [key]: marker };
} else {
const newMarkers = { ...prev };
delete newMarkers[key];
return newMarkers;
}
});
};
return (
<>
{mapData.map((loc: IFormattedData) => {
return (
<AdvancedMarker
key={loc.key}
position={loc.location}
ref={(marker) => setMarkerRef(marker, loc.key)}
clickable={true}
title={`CDB Number: ${loc.key}`}
className="map-marker"
>
<Pin
background={"#cc0099"}
glyphColor={"#000"}
borderColor={"#000"}
/>
</AdvancedMarker>
);
})}
</>
);
};
export default MapMarker;
mapData 从哪里来?循环 25,000 个标记听起来不是一个好主意。我建议从地图中获取当前边界,仅获取边界内的标记,然后循环它们。
<Map
onBoundsChanged={(bounds) => loadMarkersFromBound(bounds)} >
</Map>
我还建议消除加载函数的抖动,否则当用户在地图上移动时可能会收到太多请求。或者,就像 Airbnb 所做的那样,每当边界发生变化时,您都可以显示一个按钮来手动重新加载新边界的标记。