获取在地图上可见的所有标记(markers)使用 react-leaflet。

huangapple go评论58阅读模式
英文:

Get all markers visible on the map with react-leaflet

问题

我正在React中使用Leaflet来模仿Airbnb的效果。我不太了解最佳实践,但我考虑过:将地图上可见的标记存储在一个数组中,并在每次移动地图时更新此数组。然后根据可见的标记在地图旁边显示一个列表(例如,地点列表)。

以下是一个简单的代码,用于在地图上显示标记:

function FranceMap() {
  const { latitude, longitude }: ParisProps = ParisGpsCoordinates;

  return (
    <div
      id="map-container"
      className="..."
    >
      <MapContainer center={[latitude, longitude]} zoom={11}>
        <TileLayer
          attribution='&copy; <a href="https://stadiamaps.com/">Stadia Maps</a>, &copy; <a href="https://openmaptiles.org/">OpenMapTiles</a> &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors'
          url="https://tiles.stadiamaps.com/tiles/osm_bright/{z}/{x}/{y}{r}.png"
        />
        <MarkerClusterGroup chunkedLoading>
          {SitesLocation}
        </MarkerClusterGroup>
      </MapContainer>
    </div>
  );
}

我理解您需要使用map.getBounds(),但我不知道如何将其集成到我的代码中。

英文:

I'm using leaflet in React to reproduce an effect like Airbnb. I don't really know the best practices, but I was thinking of: storing the markers visible on the map in an array and having this array update each time the map is moved. Then display a list (of places for example) next to the map based on the visible markers.

Here's a simple code that displays the markers on the map:

function FranceMap() {
  const { latitude, longitude }: ParisProps = ParisGpsCoordinates;

  return (
        &lt;div
          id=&quot;map-container&quot;
          className=&quot;...&quot;
        &gt;
          &lt;MapContainer center={[latitude, longitude]} zoom={11}&gt;
            &lt;TileLayer
              attribution=&#39;&amp;copy; &lt;a href=&quot;https://stadiamaps.com/&quot;&gt;Stadia Maps&lt;/a&gt;, &amp;copy; &lt;a href=&quot;https://openmaptiles.org/&quot;&gt;OpenMapTiles&lt;/a&gt; &amp;copy; &lt;a href=&quot;http://openstreetmap.org&quot;&gt;OpenStreetMap&lt;/a&gt; contributors&#39;
              url=&quot;https://tiles.stadiamaps.com/tiles/osm_bright/{z}/{x}/{y}{r}.png&quot;
            /&gt;
            &lt;MarkerClusterGroup chunkedLoading&gt;
              {SitesLocation}
            &lt;/MarkerClusterGroup&gt;
          &lt;/MapContainer&gt;
        &lt;/div&gt;
      &lt;/div&gt;
  );
}

I understand that you need to use map.getBounds(), but I don't know how to integrate it into my code.

答案1

得分: 1

假设你已经将所有的标记存储在一个数组中:

const points = [
  [54, -1.5],
  [54.5, -1.5],
  [54.1, -1.5],
  [54.2, -1.6],
];

但由于这个数组可能很大,你只想根据地图上当前的边界来渲染可见的标记,你可以使用以下代码来连接各种事件以更新可见的标记:

useEffect(() => {
  if (!map) return;
  // 地图首次渲染后更新标记
  updateVisibleMarkers();

  map.on('dragend', function () {
    // 用户拖动地图以更改位置后更新标记
    updateVisibleMarkers();
  });
  map.on('zoomend', function () {
    // 用户放大/缩小地图后更新标记
    updateVisibleMarkers();
  });
}, [map]);

updateVisibleMarkers() 函数从地图获取当前的边界,然后迭代 points 数组,检查每个标记是否在边界内。如果是的话,我们将它添加到 newMarkers 数组中,然后在考虑完所有点之后,调用 setVisibleMarkers 来更新可见标记的状态:

const updateVisibleMarkers = () => {
  const bounds = map.getBounds();
  const newMarkers = [];
  for (let point of points) {
    if (bounds.contains(point)) {
      newMarkers.push(point);
    }
  }
  console.log(
    '!!! 地图边界:',
    map.getBounds(),
    ' 可见标记:',
    newMarkers
  );
  setVisibleMarkers(newMarkers);
};

可见标记的渲染如下:

<MapContainer ...>
  <TileLayer ...>
  {visibleMarkers.map((p) => (
    <Marker position={p}></Marker>
  ))}
</MapContainer>

你可以在这里查看一个可运行的 StackBlitz 示例,演示了这个功能。你会看到在拖动或缩放地图时标记会被添加/移除。

英文:

Assuming you have all the markers stored in an array:

const points = [
  [54, -1.5],
  [54.5, -1.5],
  [54.1, -1.5],
  [54.2, -1.6],
];

but as this array could be large, you only want to render the ones visible based on the current bounds on the map, you can use this code to hook into the various events in order to update the visible markers:

useEffect(() =&gt; {
  if (!map) return;
  // Updates markers after map initially renders
  updateVisibleMarkers();

  map.on(&#39;dragend&#39;, function () {
    // Updates markers after user drags the map to change position
    updateVisibleMarkers();
  });
  map.on(&#39;zoomend&#39;, function () {
    // Updates markers after user zooms in/out
    updateVisibleMarkers();
  });
}, [map]);

The updateVisibleMarkers() function gets the current bounds from the map, and iterates over the points array checking whether each marker is within the bounds. If it is, we add it to the newMarkers array, then after all the points have been considered, setVisibleMarkers is called to update the visible marker state:

const updateVisibleMarkers = () =&gt; {
  const bounds = map.getBounds();
  const newMarkers = [];
  for (let point of points) {
    if (bounds.contains(point)) {
      newMarkers.push(point);
    }
  }
  console.log(
    &#39;!!! map bounds:&#39;,
    map.getBounds(),
    &#39; visible markers: &#39;,
    newMarkers
  );
  setVisibleMarkers(newMarkers);
};

The visible markers are rendered as follows:

&lt;MapContainer ...&gt;
  &lt;TileLayer ...&gt;
  {visibleMarkers.map((p) =&gt; (
    &lt;Marker position={p}&gt;&lt;/Marker&gt;
  ))}
&lt;/MapContainer&gt;

There's a working StackBlitz example to showcase the functionality. You will see the markers getting added/removed as you drag or zoom the map.

huangapple
  • 本文由 发表于 2023年7月28日 01:30:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/76782173.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定