Построение большого количества маркеров на карте реактивных листовок идет слишком медленно - PullRequest
0 голосов
/ 03 октября 2018

У меня есть набор данных из 4360 геомаркеров, которые я хочу отобразить на карте Leaflet.CircleMarker работает просто отлично, и производительность построенной карты в порядке.Однако построение карты занимает слишком много времени (около 20 секунд).Без реакции на создание маркеров требуется доля секунды.Есть ли какая-то подсказка или уловка производительности, которую можно использовать для ускорения построения карты?

import * as React from 'react';
import { Component } from 'react';
import { LatLng } from 'leaflet';
import { Map, TileLayer, CircleMarker, Popup } from 'react-leaflet';

export default class Editor extends Component {
    state = {
        lat: 51.505,
        lng: -0.09,
        zoom: 13,
        markers : [ ]
    }

    componentDidMount() {
        // data.csv contains several thousands of items
        fetch('data.csv')
            .then(res => res.json())
            .then(data => this.setState({ markers: data.items.map(v => new LatLng(v.lat, v.lng)) }));
    }

    render() {
        const markers = this.state.markers.map((v, i) =>
            <CircleMarker key={i} center={v} radius={3} />);
        return (
            <Map center={new LatLng(51.505, -0.09)} zoom={this.state.zoom}>
                <TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
                {markers}
            </Map>
        )
    }
}

Прямые манипуляции с DOM делают это за доли секунды:

export default class ItemsMap extends React.Component {
  state = { items : [ ] };
  map : L.Map;

  componentDidUpdate(prevProps : any, prevState : any) {
    this.renderItems(this.state.items);
  }

  componentDidMount() {
    const node : any = ReactDOM.findDOMNode(this);
    this.map = L.map(node).setView([51.505, -0.09], 13);
    L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 18 }).addTo(this.map);

    fetch('data.csv')
      .then(res => res.json())
      .then(data => this.setState({ items: data.items.map(v => new LatLng(v.lat, v.lng)) }));
  }

  renderItems(items : Array<any>) {        
    items.forEach(item => {
      L.circleMarker(
        [ item.lat, item.lng ],
        { radius : 3 }
      ).addTo(this.map);
    });
  }

  render() {
    return (
      <div id="mapid" style={{ height: '100%' }} />
    );
  }
}

1 Ответ

0 голосов
/ 02 января 2019

Один из методов, который следует рассмотреть, - это для визуализации только подмножества маркеров в пределах данной границы карты , это может значительно сократить время, необходимое для повторного рендеринга компонентов, а также количество узлов DOMсозданный:

 componentDidMount() {
    fetch('data.csv')
   .then(res => res.json())
   .then(data => {
       this.allMarkers = data.items.map(v => new LatLng(v.lat, v.lng));
       displayMarkers();
    });
 }

, где

displayMarkers() {
   const map = this.mapRef.current.leafletElement;
   const markers = this.allMarkers.filter(m =>
      map.getBounds().contains(m)
   );

   this.setState({
       markers: markers
   });
}

Демонстрация

Другая оптимизация (специфическая для листовки) будет заключаться в установке preferCanvas до true для визуализации маркеров на холсте вместо SVG :

Нужно ли отображать пути на рендере Canvas.По умолчанию все пути отображаются в SVG-рендерере.

<Map
    preferCanvas={true}
    center={new LatLng(51.505, -0.09)}
    zoom={this.state.zoom}
  >
    ... 
  </Map>

После демонстрации показано, как визуализировать 20k маркеров с помощью react-leaflet

...