Charmatzis / react-leaflet-shapefile

React-Leaflet-Shapefile | This repo is obsolete. Plz, use https://github.com/TA-Geoforce/react-leaflet-shapefile
https://github.com/TA-Geoforce/react-leaflet-shapefile
MIT License
12 stars 22 forks source link

Uncaught Error createLeafletElement() must be implemented and slow performance #2

Open corganfuzz opened 6 years ago

corganfuzz commented 6 years ago

Solved this error by adding, the following inside the example folder:

on src/Shapefile.js

Right after the ComponentWillMount () (right about line 11) , do:

ShapeFile.prototype.createLeafletElement = function createLeafletElement () {}

Now, I've tried to add the following file block.zip, which can be found here https://www.data.boem.gov/Main/Mapping.aspx: (4th element on table) which has around 10.000 features (about 4.6MB)

But the map performs really slow, when the layer is on. I suspect this is because I'm trying to move ALL features at the same time, so map and feature layers move together. Slowness goes away when layer is deselected.

Any Idea how could I make it faster ?

package.json

  "peerDependencies": {
    "catiline": "2.9.3",
    "leaflet": "^1.2.0",
    "prop-types": "^15.5.10",
    "react": "^15.6.1",
    "react-leaflet": "^1.7.1",
    "shpjs": "^3.3.2"
  },
  "devDependencies": {
    "babel-cli": "^6.8.0",
    "babel-core": "^6.8.0",
    "babel-eslint": "^8.0.3",
    "babel-loader": "^6.2.4",
    "babel-preset-es2015": "^6.6.0",
    "babel-preset-react": "^6.0.15",
    "babel-preset-stage-0": "^6.1.18",
    "catiline": "2.9.3",
    "eslint": "^4.12.1",
    "eslint-plugin-react": "^7.5.1",
    "jquery": "*",
    "leaflet": "^1.2.0",
    "prop-types": "^15.5.10",
    "react": "^15.6.1",
    "react-dom": "^15.6.1",
    "react-leaflet": "^1.7.1",
    "requirejs": "^2.3.2",
    "shpjs": "^3.3.2",
    "webpack": "^1.13.0",
    "webpack-dev-server": "^1.12.1"
theweaklink commented 6 years ago

Hi there!

I'm having the same performance issues as described as @corganfuzz (btw thanks a lot for finding the createLeafletElement fix!): as soon as the shapefile is above a couple Mb, the map becomes unusable (e.g. panning sideways). I tried the non-react shapefile leaflet and it is quite slow too (not as slow, so somehow the react adds a little more).

@corganfuzz did you find a way to work around it?

corganfuzz commented 6 years ago

So I wouldn't call it a workaround ( or a solution per se) but here's what I did. Read this article.

I've converted the shapefiles to js files, like the article says using QGIS and software the article had.

Although, the old software that runs in windows was too old and unsupported, so I didnt use it. After that, I've load it, under src/fakedata. Also, I chose very small shapefiles files.

Once I had them all nice and reduced, I've used the components and had them as turn /off layers.

Obviously , this is not a solution but I do believe these files should be stored on the server side (and reduced in sized with qgis or something) as the article said. But I couldn't figure out how to call the .shp files without the freaking upload button, so I transformed them to js and made the modifications above .

NOTE: QGIS works on mac and PC , but I find out the PC version is better as it crashes less, specially with big files

theweaklink commented 6 years ago

Thanks for sharing! I definitely agree with your comment: ideally everything should be stored on the server side. In my case the shp file list is actually dynamic so I need to have any server side process (decimation, conversion) automated which seems possible but add some extra complexity to the mechanism. Since yesterday I started to look at these things (at this point I don't know if it would work or not but I'll keep you posted as I try them out):

Here is the react package for leaflet vector grid: https://github.com/mhasbie/react-leaflet-vectorgrid Here is a link with lots of resources on Vector Tiles too: https://github.com/mapbox/awesome-vector-tiles

About getting the file directly from a URL (e.g. statically served file), this worked from me:

// shp_url is the URL to the shape file

var oReq = new XMLHttpRequest();
oReq.open("GET", shp_url, true);
oReq.responseType = "arraybuffer";

var that = this;
oReq.onload = function (oEvent) {
  var arrayBuffer = oReq.response;
  if (arrayBuffer) {
      that.setState({ geodata: arrayBuffer });
      that.setState({ isadded: true });
  }
};

oReq.send(null);

Hopefully it works for you too? But it doesn't solve the performance issue.

corganfuzz commented 6 years ago

Ahh...Now I remember what I did specifically, sorry I forgot.

  1. I read the react-leaflet documentation and find out the component supports in fact geojson and json. :)

  2. Selected 2 fairly small shp files, and reduced them with QGIS as much as possible, and converted them to js files added a

const uklayer = [... coordinates crap] export default uklayer inside them

  1. wrote the following, and use those converted shp files as layers.
    let britLayer = (
      <LayersControl.Overlay checked name="UK layer">
        <FeatureGroup color="#82c23d">
          <GeoJSON data={this.state.ukjson}
          />
        </FeatureGroup>
      </LayersControl.Overlay>
    );

Thanks for the valuable info, I will use this on the future and do let me know how to solve the problem.

P.D. I posted this question regarding the upload button in the overlfows, and nobody answered, please go ahead and do so, if you like.