微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

react-leaflet:在呈现新标记之前清除标记簇

如何解决react-leaflet:在呈现新标记之前清除标记簇

TLDR;有没有办法使用 react-leaflet 和 react-leaflet-markercluster 清除标记簇中的所有标记

编辑:是的,有!我刚刚向 MarkerClusterGroup 添加一个关键道具,正如@SethLutske 所推荐的那样。现在,每次重新渲染地图时,之前的标记都会被移除,只保留新的标记

<MarkerClusterGroup
    key={uuidv4()}  
    spiderfydistanceMultiplier={1}
    showCoverageOnHover={true}
>

我在我所在州的公安机关工作。有一个 API 可以从我所在州的所需城市获取一组监控摄像机。我正在使用 React PWA 来检索这些摄像机的图像,因此警察可以使用我的应用程序进行实时监控。警察在系统中进行身份验证,使用表格按所在城市过滤摄像头,结果显示在地图中,并带有指示每个摄像头位置的标记。触摸标记时,会显示一个弹出窗口,其中包含该相机的信息,以及一个按钮,触摸时会在新页面显示相机图像。

Map markers and popup

我选择 Leaflet 和 react-leaflet 进行地图渲染,并选择 react-leaflet-markercluster 将彼此相邻的标记分组。我有一个小问题:如果用户按城市过滤相机,然后他返回表单并决定按不同的城市过滤,我想要发生的行为是:

但是会发生这样的情况:来自前一个城市的标记保留在地图中,并带有一个空弹出窗口。

Marker groups from different cities

我的目标:在添加新城市的标记之前,我想清除过去的城市标记

这是我的 MapContainer。尽管存在我提到的错误,但它运行良好。

      <MapContainer            
          center={[-26.627817,-51.196288]}
          zoom={6}
          scrollWheelZoom={false}
          style={{ height: '100vh',width: '100wh' }}
      >
        {//<ClearLayers /> this clears the entire map,even the tile layer,leaving it blank
        }
          <TileLayer
          attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
          url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
          />
          <MarkerClusterGroup
              spiderfydistanceMultiplier={1}
              showCoverageOnHover={false}
          >
              {cameras.map((camera: Camera) => (
                  <Marker icon={iconBTV} key={camera.name} position={[camera.latitude,camera.longitude]}>
                      <Popup>
                        {camera.name} <br /> {camera.description} <br />
                        <Link
                          to={{
                            pathname: "/cameraScreen",}}
                          style={{ textdecoration: 'none' }}
                        >
                          <button
                            style={{marginTop: "1rem"}}
                            onClick={(e) => insertLog(e,camera)}
                          >Ver câmera</button>
                        </Link>                            
                      </Popup>
                  </Marker>
              ))}
          </MarkerClusterGroup>
      </MapContainer>

我尝试使用此功能,但它不能如我所愿。它使地图出错,使其完全空白。

function ClearLayers() {
  const map = useMap();
  map.eachLayer(function (layer) {
    map.removeLayer(layer);
  });
  return null
}

在这里搜索并接近解决方案:我能够通过使用 Leaflet 的核心 API 清除过去的城市标记并留下 react-leaflet-markercluster 包装器 as shown in this answer。在向 MCG 添加标记之前,我确实执行了 clearLayers(),这就是诀窍。这是我尝试做的:

    import * as L from 'leaflet';
    import 'leaflet.markercluster';

    import { useMap } from 'react-leaflet';
    import { useContext,useEffect } from 'react';
    import { Link } from 'react-router-dom';
    import CameraContext from '../../contexts/CameraContext';

    const mcg = L.markerClusterGroup({
        chunkedLoading: true,showCoverageOnHover: false,});

    const MarkerCluster = ({ markers,icon }) => {
        const { setCamera } = useContext(CameraContext);

        const inserirLog = (e,camera) => {
            setCamera(camera);
            var ajax_log = new XMLHttpRequest();
            ajax_log.open('GET',`https://fakeurl.sc.gov.br/api/ajax-log-bemtevi.PHP?camera=${camera.nome}&servidor=${camera.servidor}`);
            ajax_log.send();
        }   

        console.log(markers);
        const map = useMap();
        useEffect(() => {
            mcg.clearLayers();
            const markerList = markers.map((camera) => {
                return L.marker(new L.LatLng(camera.latitude,camera.longitude),{
                    icon: icon,}).bindPopup(
                    `
                    ${camera.name} <br /> ${camera.description} <br />
                    <Link
                    to={{
                        pathname: "/cameraScreen",}}
                    style={{ textdecoration: 'none' }}
                    >
                    <button
                        style={{marginTop: "1rem"}}
                        onClick={(e) => insertLog(e,camera)}
                    >Watch camera</button>
                    </Link>
                    `
                );
            });
            mcg.addLayers(markerList);
            map.fitBounds(mcg.getBounds());
            map.addLayer(mcg);
        },[markers,icon,map]);

        return null;
    };

    export default MarkerCluster;

这样做后,我无法在 Popup 中注入 JSX,也无法使用 react-router-dom 中的 Link 组件。我也无法在上下文中保存相机对象以在下一页中进一步使用它。所以我最终坚持使用我当前的代码,尽管有这个“无法清除过去的城市标记”的错误

因此,当使用 React 组件进行 Leaflet map 和 Marker Cluster 时,我想有一种方法可以清除过去的城市标记。如果 MarkerClusterGroup 有一个钩子,就像 Leaflet 地图有一个钩子一样,我想这会更容易做到:我需要做的就是这样简单的事情:

    const markercluster = useMarkerClusterGroup();
    markercluster.clearLayers();

但是,据我所知,react-leaflet-markercluster 中没有钩子。

解决方法

您可以向 key 添加一个 MarkerClusterGroup 属性,并在您希望集群完全重新渲染时更改它。

<MarkerClusterGroup
  key={somekey}
  spiderfyDistanceMultiplier={1}
  showCoverageOnHover={false}
>

我不确定触发标记更改的逻辑是什么,但在相同的逻辑中,当标记更改时,会生成一个新的唯一值(无论是递增的简单计数器,还是新的 uuid ),将 key 设置为该新值,整个组件应该卸载并重新安装。虽然如果有大量标记,这对性能来说不是很好,但这听起来像是您想要做的。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。