calvinmetcalf / leaflet.shapefile

Shapefile in Leaflet
http://calvinmetcalf.github.io/leaflet.shapefile/
MIT License
259 stars 119 forks source link

zoom to certain shapefile #10

Open rakucmr opened 10 years ago

rakucmr commented 10 years ago

How can I zoom to certain shapefile? I have tried like this but not working:

var romania = new L.Shapefile('Romania.zip',{style: romaniaStyle}); romania.addTo(map); map.fitBounds(romania.getBounds());

calvinmetcalf commented 10 years ago

it will load the files async so if you get bounds before it is on the map then it will not have bounds.

rakucmr commented 10 years ago

Yes you have right, the problem comes when I don't place catiline.js, shp.js in the root of the website, because the worker try to load shp.js from the root and it is located in other directory

rakucmr commented 10 years ago

The only way to make it work as to fill all path in leaflet.shpfile.js: L.Shapefile = L.GeoJSON.extend({
initialize: function (file, options) { if(typeof cw !== 'undefined'){ this.worker = cw(function(data,cb){ importScripts('http://localhost/harta/media/site/js/shp.js'); shp(data).then(cb); }); } I tink the probem comes from workers, why they need to load again shp.js if it is already added in header of page?

calvinmetcalf commented 10 years ago

because workers have separate scope and need to import the scripts themselves, using catiline is optional and if you don't include the script tag for it then it will just do stuff not in a web worker

oscarhidalgo commented 10 years ago

var romania = new L.Shapefile('Romania.zip',{style: romaniaStyle}); romania.addTo(map); var controlbounds_romania = window.setInterval(function(){ if (romania.getBounds().isValid()== true) { map.fitBounds(romania.getBounds()); window.clearInterval(controlbounds_romania); } }, 500);

davidlukerice commented 9 years ago

I'll add in a solution in case anyone is still having this issue.

First, the latest shp.js now allows you to pass in an importUrl from with the https://github.com/calvinmetcalf/leaflet.shapefile/pull/23 PR. This should let you put the shp.js file on the server wherever you want. So in your case you would call

L.Shapefile('Romania.zip',{style: romaniaStyle}, 'http://localhost/harta/media/site/js/shp.js')

Second is the issue of knowing when a shape file is finally asynchronously loaded in. @oscarhidalgo's solution works by constantly checking if the shape has loaded in (has valid bounds) and then fits the map to the shape. You can retain a bit more control by using an XMLHttpRequest to first download the zip file and then pass the binaryArray into the L.Shapefile function. You'd still have to do the setInterval checks since the webworker still processes asynchronous, but at least you have control over any network issues/latency that may be present.

var req = new XMLHttpRequest();
req.open('GET', 'Romania.zip');
req.responseType = 'arraybuffer';
req.onload = function(event) {
    if (req.response) {
        var shapeLayer = L.shapefile(req.response, romaniaStyle, 'http://localhost/harta/media/site/js/shp.js');
        fitMapBoundsIntervalCheck();
    }
    else {
      // handle error
    }
};
req.send(null);
devdattaT commented 8 years ago

I believe the 'data:loaded' event added in 1b6ca4313237f9fc876b856e3d43e847f385ab79 can be used to get the event when all the data is loaded.

Using this event, you can easily zoom to the region by using the following code:

shpfile = new L.Shapefile(e.target.result,{isArrayBufer:true});
shpfile.on("data:loaded", function (e){
    m.fitBounds(shpfile.getBounds());
});
shpfile.addTo(m);