Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I'm trying to show different GeoJSON layers at different zoom layers using the Leaflet API. I can load and display all three layers at once (though I don't actually want them all to show at once). I can load and display them at different zoom levels.

I have the code set up so that at Zoom levels 1-6, the map will show one GeoJSON layer. At levels 7-10, it will show another, and at levels 11+ it will show a third. Displaying them works. What I'm trying to get working now is turning the others off if one is displayed. Going from 1-6 to 7-10 works (meaning that it turns off the 1-6 layer correctly), but not from 7-10 to 11+ (meaning that the 7-10 layer sticks around) and I can't figure out why (it uses the same code).

Here's the ajax for the GeoJSON layers:

function getJson(defaultStyle, map, simp, geojsonLayer){
var url = 'file' + simp + '.json';
map.removeLayer(geojsonLayer);
geojsonLayer.clearLayers();
$.getJSON(url, function(data){
    geojsonLayer = L.geoJson(data, {
        style: defaultStyle,
        onEachFeature: onEachFeature
    });
    geojsonLayer.addTo(map);
});
}

And here's the main function that calls the ajax depending on the zoom. simpCounter is set to 0 initially.

map.on('zoomend', function(e) {
if (map.getZoom() >= 7 && map.getZoom() <= 10) {
    if (simpCounter == 0 || simpCounter == 2) {
    getJson(defaultStyle, map, 60, geojsonLayer);
    simpCounter = 1;
    }
} else if (map.getZoom() >= 11) {
    if (simpCounter == 0 || simpCounter == 1) {
    getJson(defaultStyle, map, 35, geojsonLayer);
    simpCounter = 2;
    }
}
});

So again, the first transition turns off the old layer correctly, the but second transition does not. Thanks for the help.

share|improve this question
    
Just to clarify, it IS turning on the json for 11+ and NOT turning off 7-10? –  RomaH Nov 23 '12 at 21:56
    
That is correct. –  Josh Nov 24 '12 at 9:39

2 Answers 2

up vote 5 down vote accepted

Try this instead:

function getJson(simp){  //Removed unneeded arguments here
    var url = 'file' + simp + '.json';
    map.removeLayer(geojsonLayer);
    //geojsonLayer.clearLayers();  I don't believe this needed.
    $.getJSON(url, function(data){
        geojsonLayer = L.geoJson(data, {
            style: defaultStyle,
            onEachFeature: onEachFeature
        });
        geojsonLayer.addTo(map);
    });
}

And for your calling function:

map.on('zoomend', function(e) {
    if (map.getZoom() >= 7 && map.getZoom() <= 10) {
        if (simpCounter == 0 || simpCounter == 2) {
        getJson(60);
        simpCounter = 1;
        }
    } else if (map.getZoom() >= 11) {
        if (simpCounter == 0 || simpCounter == 1) {
        getJson(35);
        simpCounter = 2;
        }
    } else if (map.getZoom() <= 7) { //Return to original data
        if (simpCounter == 1 || simpCounter == 2) {
        getJson(XX); //Fill out with correct file name
        simpCounter = 0;
        }
    }
});

When you are passing the arguments map, geojsonLayer and defaultStyle in the call getJson(defaultStyle, map, 60, geojsonLayer); you are creating new instances of the objects. You then perform work on the instances which may reflect on the screen but once it get back to the 'main loop' it basically forgets everything it just did and returns to the previous state.

Since I am guessing you defined defaultStyle, map, and the initial geojsonLayer population in the global scope you just have to call them, no need to pass them. With the adjustments I made it changes the global map so changes persist after function calls finish.

This solution worked for me. You can see the entire file contents I made here: http://pastebin.com/yMYQJ2jK

I also define a final zoom level for 1-7 so you can see you initial JSON data when you return to the initial zoom level, otherwise it is lost and is never called back unless you reload the page!

share|improve this answer
    
Thanks. I didn't realize that the passing in variables creates temp instances. –  Josh Nov 26 '12 at 5:36
    
Yeah the only way to keep the changes they way you were doing it would be to pass it back with a return statement. Using globals in javascript seems common, so doing this way will be the easiest to complete your task. –  RomaH Nov 26 '12 at 13:33
    
That makes sense. I had read recently in a Best Practices book not to use globals, but apparently I was misusing the alternative. Thanks. –  Josh Nov 26 '12 at 15:43
    
It is best practice in all programming languages not to use globals, It is easier to track bugs. But best practice is only a rule of thumb. Most javascript-in-page uses seem light enough that side-effects can be easily managed. If you are writing an entire module or external js I would avoid globals. –  RomaH Nov 26 '12 at 17:23

leaflet has a layergroup collection type of data structure and also a layer control interface that you can toggle on and off once you code it as event listeners on checkbox.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.