Come utilizzare FeatureGroup di Leaflet con OverlappingMarkerSpiderfier in React-leaflet?

Oct 23 2020

Ho problemi nell'integrazione di OverlappingMarkerSpiderfier con React-Leaflet e nell'utilizzo di FeatureGroup per la panoramica sulla mappa. I FeatureGroup sono davvero utili quando si dispone di una logica di panoramica complicata.

Ecco una semplice demo JS . I marker spiderfy e il pulsante Pan funzionano senza problemi.

Ecco la demo del foglietto di reazione . La panoramica fallirà con il seguente errore se spiderfy è abilitato / controllato nell'interfaccia utente. Questo è basato su questo post SO .

layer.getLatLng is not a function

Penso che il problema sia che con JS normale, posso aggiungere l'array di marcatori a entrambi omse in modo featureGroupimperativo, ma con React-leaflet, non vedo come posso ottenere lo stesso risultato.

È l'errore perché il <Spiderfy>livello non ha una getLatLngfunzione per qualche motivo anche se sto estendendo il MapLayer .

Non sono sicuro di ciò che deve essere risolto, la versione JS sembra funzionare quindi la libreria OverlappingMarkerSpiderfier probabilmente non necessita di modifiche. Potrebbe essere un problema / limitazione specifico del volantino React che può essere risolto con un FeatureGroup / MapLayer personalizzato?

Risposte

1 VadimGremyachev Oct 24 2020 at 17:51

Sembra l'errore

layer.getLatLng non è una funzione

si verifica poiché la funzione FeatureGroup.getBounds prevede che i livelli sottostanti implementino uno getBoundso i getLatLngmetodi, il che non è il caso del Spiderfy.jscomponente personalizzato in cui container ( layerContainerprop) è di L.layerGrouptipo.

Un'opzione da considerare sarebbe il refactoring del Spiderfy.jscomponente:

  • abbandonare L.layerGroupcome contenitore di livelli
  • poiché viene utilizzata una versione recente di React ( 16.8o superiore), sostituire il ES6 classcomponente con la funzione per implementare il Spiderfycomponente

Spiderfy.js componente

import React, { useEffect } from "react";
import { withLeaflet, MapLayer, useLeaflet } from "react-leaflet";
import L from "leaflet";
import "overlapping-marker-spiderfier-leaflet/dist/oms";

function Spiderfy(props) {
  const { map, layerContainer } = useLeaflet();
  const oms = new window.OverlappingMarkerSpiderfier(map);
  oms.addListener("spiderfy", (markers) => {
    markers.forEach((m) => m.closePopup()); //force to close popup
    if (props.onSpiderfy) props.onSpiderfy(markers);
  });
  oms.addListener("unspiderfy", (markers) => {
    if (props.onUnspiderfy) props.onUnspiderfy(markers);
  });
  oms.addListener("click", (marker) => {
    if (props.onClick) props.onClick(marker);
  });

  useEffect(() => {
    layerContainer.eachLayer((layer) => {
      if (layer instanceof L.Marker) {
        oms.addMarker(layer);
      }
    });
  }, [oms,layerContainer]);

  return <div>{props.children}</div>;
}

export default withLeaflet(Spiderfy);

In questo modo la FeatureGroup.getBoundsfunzione dovrebbe restituire il risultato atteso, identico a quello fornito nella semplice demo JS .

Esempio a forcella

1 LouisChristopher Oct 26 2020 at 06:36

Come correttamente sottolineato da Vadim , L.layerGroupnon implementa getBounds.

Lo svantaggio principale dell'abbandono di un gruppo di livelli è che anche i componenti che non sono figli del componente Spiderfy sono sottoposti a spiderfy poiché utilizza il layerContainer

  • Guarda questa demo . Se guardi il registro della console, la markerCountvariabile è 4 anche se ci sono solo tre marcatori come figli di Spiderfy.

Guardando la documentazione di Leaflet, possiamo usare L.featureGroup invece di un layerGroup in quanto è semplicemente un'estensione del layerGroup.

const el = L.featureGroup([], this.getOptions(props));

  • Demo , puoi vedere che la markerCountvariabile è 3 e non 4

A seconda del caso d'uso, la nidificazione di gruppi di funzionalità come questo non sarà un problema. Facoltativamente puoi dare un'occhiata ai sottogruppi