Como usar o FeatureGroup do Leaflet com OverlappingMarkerSpiderfier no react-leaflet?

Oct 23 2020

Estou tendo problemas para integrar OverlappingMarkerSpiderfier ao React-Leaflet e usar o FeatureGroup para deslocar o mapa. FeatureGroups são realmente úteis quando você tem uma lógica panorâmica complicada.

Aqui está uma demonstração simples de JS . Os marcadores spiderfy e o botão panorâmico funcionam sem problemas.

Aqui está a demonstração do folheto reativo . A panorâmica falhará com o seguinte erro se spiderfy estiver habilitado / verificado na IU. Isso é baseado neste post do SO .

layer.getLatLng is not a function

Acho que o problema é que com JS regular, posso adicionar o array markers a ambos omse ao featureGroupimperativamente, mas com React-leaflet, não vejo como posso obter o mesmo resultado.

É o erro porque a <Spiderfy>camada não tem getLatLngfunção por algum motivo mesmo estando estendendo o MapLayer .

Não tenho certeza do que precisa ser consertado, a versão JS parece funcionar, então a biblioteca OverlappingMarkerSpiderfier provavelmente não precisa de alterações. Pode ser um problema / limitação específico do folheto React que pode ser corrigido com um FeatureGroup / MapLayer personalizado?

Respostas

1 VadimGremyachev Oct 24 2020 at 17:51

Parece que o erro

layer.getLatLng não é uma função

ocorre porque a função FeatureGroup.getBounds espera que as camadas subjacentes implementem um dos métodos getBoundsou getLatLng, o que não é o caso com o Spiderfy.jscomponente personalizado em que o contêiner ( layerContainerprop) é do L.layerGrouptipo.

Uma opção a ser considerada seria refatorar o Spiderfy.jscomponente:

  • abandonar L.layerGroupcomo um recipiente de camada
  • uma vez que uma versão recente do React é utilizada ( 16.8ou acima), substitua o ES6 classcomponente pela função para implementar o 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);

Dessa forma, a FeatureGroup.getBoundsfunção deve retornar o resultado esperado, idêntico ao fornecido na demonstração JS simples .

Exemplo bifurcado

1 LouisChristopher Oct 26 2020 at 06:36

Como Vadim corretamente apontou , L.layerGroupnão implementa getBounds.

A principal desvantagem de abandonar um layerGroup é que os componentes que não são filhos do componente Spiderfy também são spiderficados, pois ele usa o layerContainer

  • Veja esta demonstração . Se você olhar o log do console, a markerCountvariável é 4, embora haja apenas três marcadores como filhos de Spiderfy.

Olhando a documentação do Leaflet, podemos usar L.featureGroup em vez de um layerGroup, pois é simplesmente uma extensão do layerGroup.

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

  • Demo , você pode ver que a markerCountvariável é 3 e não 4

Dependendo do seu caso de uso, aninhar grupos de recursos como este não será um problema. Opcionalmente, você pode dar uma olhada nos subgrupos