Search code examples
leafletgeojson

Loading multiple GeoJSONs, how to use different markers/pop-ups for each


I spent all day trying to figure out how to load more than one GeoJSON. Finally figured it out thanks to an earlier SE question. Now I'm stuck trying to symbolize each GeoJSON

I would like to symbolize each GeoJSON differently, of course, but I'm really at a loss as to where to go next. The old code (at the bottom) worked fine on a single layer, but I don't know how to modify it for the individual geojsons.

I hope my code isn't too bad or unreadable!

//blahblahblah, initial headers, etc

//load breweries GeoJSONs from external file
var breweries = new L.geoJson();
breweries.addTo(map);

$.ajax({
    dataType: "json",
    url: "breweries.geojson",
    success: function(data) {
        $(data.features).each(function(key, data) {
            breweries.addData(data);
        });
    }
}).error(function() {});

//load wineries GeoJSON from external file
var wineries = new L.geoJson();
wineries.addTo(map);

$.ajax({
    dataType: "json",
    url: "winetest.geojson",
    success: function(data) {
        $(data.features).each(function(key, data) {
            wineries.addData(data);
        });
    }
}).error(function() {});


//skip this intermediate stuff


//load Brewery GeoJSON from an external file
$.getJSON("breweries.geojson", function(data) {
    var pintGlass = L.icon({
        iconUrl: 'glass.png',
        iconSize: [24, 48]
    });

    var popupMarker = L.geoJson(data, {
        pointToLayer: function(feature, latlng) {
            var marker = L.marker(latlng, {
                icon: pintGlass
            });
            //popup shows NAME, ADDRESS, URL and opens the URL in a new window/tab
            marker.bindPopup("<strong>" + feature.properties.NAME + "</strong><br/>" + feature.properties.STREETNUM + " " + feature.properties.STREET + ", " + feature.properties.CITY + "<br/>" + "<a target = _blank href=" +
                feature.properties.URL + ">" + feature.properties.URLDISPLAY + "</a>");
            return marker;
        }
    });
});

Solution

  • First of all, you can move the pintGlass icon definition outside of the $.getJSON callback function, since it doesn't depend on the value of the returned data:

    var pintGlass = L.icon({
      iconUrl: 'glass.png',
      iconSize: [24, 48]
    });
    

    Then, if you want to access your L.geoJson layer outside the $.getJSON callback function (for instance, if you are going to refer to it when building a layer control later), you will also need to define that first outside of $.getJSON. You can actually create an empty L.geoJson object by passing it a false as its first parameter, while still setting the options, which will be applied to any data you add to it later:

    var popupMarker = L.geoJson(false, {
        pointToLayer: function(feature, latlng) {
            var marker = L.marker(latlng, {
                icon: pintGlass
            });
            //popup shows NAME, ADDRESS, URL and opens the URL in a new window/tab
            marker.bindPopup("<strong>" + feature.properties.NAME + "</strong><br/>" + feature.properties.STREETNUM + " " + feature.properties.STREET + ", " + feature.properties.CITY + "<br/>" + "<a target = _blank href=" +
                feature.properties.URL + ">" + feature.properties.URLDISPLAY + "</a>");
            return marker;
        }
    }).addTo(map);
    

    Then, your $.getJSON function won't have to do anything but add the data to your layer:

    $.getJSON("breweries.geojson", function(data) {
        popupMarker.addData(data);
    });
    

    Now it should be relatively simple to copy and modify this code to handle wineries. Assuming you have an icon called grapes.png, it would look like this:

    var wineIcon = L.icon({
      iconUrl: 'grapes.png',
      iconSize: [32, 32]
    });
    
    var wineMarker = L.geoJson(false, {
      pointToLayer: function(feature, latlng) {
        var marker = L.marker(latlng, {
          icon: wineIcon
        });
        //popup shows NAME, ADDRESS, URL and opens the URL in a new window/tab
        marker.bindPopup("<strong>" + feature.properties.NAME + "</strong><br/>" + feature.properties.STREETNUM + " " + feature.properties.STREET + ", " + feature.properties.CITY + "<br/>" + "<a target = _blank href=" +
          feature.properties.URL + ">" + feature.properties.URLDISPLAY + "</a>");
        return marker;
      }
    }).addTo(map);
    
    $.getJSON("winetest.geojson", function(data) {
      wineMarker.addData(data);
    });
    

    As for the layer controls, that is a separate question, but one that should be easy enough to answer by looking at the layer control tutorial.

    Here is an example fiddle with some dummy data showing everything at work:

    http://jsfiddle.net/nathansnider/tuppLt0b/

    And another example, in which the L.geoJson has pointToLayer and onEachFeature broken out into separate functions:

    http://jsfiddle.net/nathansnider/Lo8cmuvt/

    (Incidentally, the $.ajax routine at the beginning of your code is redundant, since $.getJSON is a shorthand method that does the exact same thing.)