Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Leaflet layer control for basemap group layers

Tags:

leaflet

Succinctly, I need groups of layers to be controlled by the leaflet layer control, two to three at a time. In this JSFiddle, when changing basemaps, the hydro overlay needs to persistently stay on top of the various basemaps.

If you run and use the layer control in the top right, you will notice how the hydro overlay will turn off when you switch to imagery and will stay off unless you switch to topographic and back to national geographic. This is the behavior I have been able to reliably reproduce. If you play with it, you can see some pretty weird stuff is going on.

Any input or suggestions for better ways to accomplish this are welcome. The solution does need to use the layer control to switch the basemap while keeping the hydro overlay on top. Otherwise, I am completely open to alternative solutions.

If you are curious before jumping over to the JSFiddle, here is the JavaScript...

// initialize map
var map = L.map('map', {
    center: [45.7067, -121.5217], // Hood River, OR
    zoom: 7
});

// hydrology overlay layer
var hydro = L.esri.tiledMapLayer('http://hydrology.esri.com/arcgis/rest/services/WorldHydroReferenceOverlay/MapServer');

// basemap layer groups so the hydro overlay always overlays the various basemaps
var nationalGeographic = L.layerGroup([
        hydro,
        L.esri.basemapLayer('NationalGeographic')
    ]),
    esriTopo = L.layerGroup([
        hydro,
        L.esri.basemapLayer('Topographic')
    ]),
    esriShadedRelief = L.layerGroup([
        L.esri.tiledMapLayer('ShadedReliefLabels'),
        hydro,
        L.esri.basemapLayer('ShadedRelief')
    ]),
    esriImagery = L.layerGroup([
        hydro,
        L.esri.basemapLayer('Imagery')
    ]);

// add default layers to map
map.addLayer(esriTopo);

// json object for layer switcher control basemaps
var baseLayers = {
    "National Geographic": nationalGeographic,
    "Esri Topographic": esriTopo,
    "Shaded Relief": esriShadedRelief,
    "Imagery": esriImagery
};

// add layer groups to layer switcher control
var controlLayers = L.control.layers(baseLayers).addTo(map);
like image 377
knu2xs Avatar asked Jul 17 '14 14:07

knu2xs


People also ask

How do you add a layer to a group in Leaflet?

Step 1 − Create a Map object by passing a <div> element (String or object) and map options (optional). Step 2 − Create a Layer object by passing the URL of the desired tile. Step 3 − Add the layer object to the map using the addLayer() method of the Map class.

What is a Leaflet layer?

In Leaflet, a “layer” is anything that moves around when the map is moved around. Before seeing how to create them from scratch, it's easier to explain how to do simple extensions.

What is Leaflet Featuregroup?

Extended layerGroup that also has mouse events (propagated from members of the group) and a shared bindPopup method. Implements ILayer interface.


1 Answers

The solution turns out to be explicitly setting the z index of the hydro layer. Searching for the z index unearthed this discussion on StackOverflow with a reference to an excellent example by Bobby Sudekum. Although I did not implement Bobby's solution directly, it did lead me to deeper investigation of the properties and methods for Leaflet TileLayer in the API.

Specifically, the zIndex option turned out to be the solution. It is worth noting the zIndex is set to five for this to work. The Layer Control automatically sets the z-index of the layers it is controlling. Hence, the original problem was the hydro layer had no index, but the layers interacted with in the layer control did. As a result, the hydro layer fell to the back as soon as the Layer Control was interacted with and disappeared. Hence, with four basemap layers, the hydro layer must have a z index of five, one more than the count of basemap layers, to show up on top of any basemap layer chosen. Finally, I also implemented the detectRetina option, dramatically improving display on my MacBook Pro.

Here is the updated code accompanying an updated JSFiddle http://jsfiddle.net/FH9VF/11/.

// initialize map
var map = L.map('map', {
    center: [45.7067, -121.5217], // Hood River, OR
    zoom: 7
});

// hydrology overlay layer
var hydro = L.esri.tiledMapLayer('http://hydrology.esri.com/arcgis/rest/services/WorldHydroReferenceOverlay/MapServer', {
    zIndex: 5,
    detectRetina: true
});

// basemap layer groups so the hydro overlay always overlays the various basemaps
var nationalGeographic = L.esri.basemapLayer('NationalGeographic'),
    esriTopo = L.esri.basemapLayer('Topographic'),
    esriShadedRelief = L.esri.basemapLayer('ShadedRelief'),
    esriImagery = L.esri.basemapLayer('Imagery');

// add default layers to map
map.addLayer(esriTopo);
map.addLayer(hydro);

// json object for layer switcher control basemaps
var baseLayers = {
    "National Geographic": nationalGeographic,
    "Esri Topographic": esriTopo,
    "Shaded Relief": esriShadedRelief,
    "Imagery": esriImagery
};

// add layer groups to layer switcher control
var controlLayers = L.control.layers(baseLayers).addTo(map);
like image 109
knu2xs Avatar answered Oct 11 '22 09:10

knu2xs