在 react-leaflet 地图上构建大量标记太慢

Ale*_*hov 12 reactjs react-leaflet

我有一个包含 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>
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

直接 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%' }} />
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

Vad*_*hev 8

一种需要考虑的技术是仅渲染给定地图边界内的标记子集,它可以显着减少重新渲染组件所需的时间以及创建的 DOM 节点的数量:

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

在哪里

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

   this.setState({
       markers: markers
   });
}
Run Code Online (Sandbox Code Playgroud)

演示

另一种优化(特定于传单)将设置preferCanvastrue 在画布上呈现标记而不是 SVG

是否应在 Canvas 渲染器上渲染路径。默认情况下,所有路径都在 SVG 渲染器中渲染。

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

下面的演示演示如何呈现20K通过标记react-leaflet

  • 偏好Canvas 是一件很棒的事情。感谢您让我们知道。 (2认同)