最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Using Geojson with tons of data in react leaflet - Stack Overflow

programmeradmin2浏览0评论

I'm using GeoJson of react-leaflet to display all polygons of an area. However, when the amount of data increase to 10000, the performance turns bad and my app has performance issues, cause it slow and laggy. How can I improve GeoJSon's performance on big data? My code :

 <Header />
      <MapContainer center={[10.7743, 106.6669]} zoom={5}>
        <TileLayer
          attribution='&copy; <a href=";>OpenStreetMap</a> contributors'
          url="https://{s}.tile.openstreetmap/{z}/{x}/{y}.png"
        />
        <GeoJSON
          style={LayerStyle}
          data={polygonData.features}
          onEachFeature={onEachContry}
        />
      </MapContainer>

The data of polygonData.features is very big, it has 100k records

I'm using GeoJson of react-leaflet to display all polygons of an area. However, when the amount of data increase to 10000, the performance turns bad and my app has performance issues, cause it slow and laggy. How can I improve GeoJSon's performance on big data? My code :

 <Header />
      <MapContainer center={[10.7743, 106.6669]} zoom={5}>
        <TileLayer
          attribution='&copy; <a href="http://osm/copyright">OpenStreetMap</a> contributors'
          url="https://{s}.tile.openstreetmap/{z}/{x}/{y}.png"
        />
        <GeoJSON
          style={LayerStyle}
          data={polygonData.features}
          onEachFeature={onEachContry}
        />
      </MapContainer>

The data of polygonData.features is very big, it has 100k records

Share Improve this question edited Jan 7, 2021 at 15:35 kboul 14.6k5 gold badges47 silver badges58 bronze badges asked Dec 23, 2020 at 9:46 Nguyen TuNguyen Tu 1594 silver badges12 bronze badges 7
  • One solution could be to show geojson subsets conditionally depending on the area of the map you are when you zoom for instance on the map. If you have such a huge amount of data you should not visualize them all at once. – kboul Commented Dec 23, 2020 at 10:03
  • But I need this feature to display heatmap on my map. Do you know any solution ? – Nguyen Tu Commented Dec 23, 2020 at 11:16
  • If you could somehow share the geojson data in a github repo for example or something similar or share a url link where you fetch the data, I could try to help. – kboul Commented Dec 23, 2020 at 11:31
  • drive.google./file/d/1LQPGidSU52xXM-Pn6GXlVqVPmjKOo4lM/… This is my geojson file data I want to display. The amount of data is very big. Thank you in advance – Nguyen Tu Commented Dec 25, 2020 at 10:04
  • thank you for accepting the answer. It would be nice if you could also upvote it. – kboul Commented Dec 27, 2020 at 15:11
 |  Show 2 more ments

3 Answers 3

Reset to default 3

You can try converting your big geojson into topojson. Because

topojson eliminates redundancy, allowing related geometries to be stored efficiently in the same file

as mentioned here, you can achieve significant smaller file size and thus better performance when you render it on your leaflet map.

You can use this site to convert your huge geojson(17.1mb) to topojson(2.7mb). You can see the difference in size after converting it. Note that it does not have unlimited free conversion capability.

After that you can create your own react wrapper to render a topojson. For this purpose you can use Vadim's answer on this stackoverflow post. It needs some adaptation to be patible with react-leaflet v.3.x, and be able to add popups in each prefecture for instance, but after making some small changes you are able to visualize your huge geojson in topojson as it was a normal geojson.

function TopoJSON(props) {
  const layerRef = useRef(null);
  const { data, ...otherProps } = props;

  function addData(layer, jsonData) {
    if (jsonData.type === "Topology") {
      for (let key in jsonData.objects) {
        let geojson = topojson.feature(jsonData, jsonData.objects[key]);
        layer.addData(geojson);
      }
    } else {
      layer.addData(jsonData);
    }
  }

  function onEachFeature(feature, layer) {
    if (feature.properties) {
      const { VARNAME_3, NAME_0 } = feature.properties;
      layer.bindPopup(`${VARNAME_3}, ${NAME_0}`);
    }
  }

  useEffect(() => {
    const layer = layerRef.current;
    addData(layer, props.data);
  }, [props.data]);

  return (
    <GeoJSON ref={layerRef} {...otherProps} onEachFeature={onEachFeature} />
  );
}

and use it like this:

import topojson from "./phuong.json";

 <MapContainer ..>
      ...
     <TopoJSON data={topojson} />
  </MapContainer>

Demo

One way could be to reduce the features in your GeoJSON. The GeoJSON is huge (55MB) because it has a lot of geographic points, which could be simplified using the tool Mapshaper (mapshaper).

Before

After

So, the other way to approach this is using the Canvas Renderer. There's a package for a Leaflet Canvas marker layer. The issue is by default, Leaflet creates dom nodes for each feature that really hit performance with big layers like yours. The marker primitives, like Circle Marker can be rendered to canvas by default, but things like Icons take a little more work to render.

发布评论

评论列表(0)

  1. 暂无评论