7

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);
knu2xs
  • 910
  • 2
  • 11
  • 23

2 Answers2

6

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);
Community
  • 1
  • 1
knu2xs
  • 910
  • 2
  • 11
  • 23
3

You need to do something like this:

//define base layers
var osmUrl='http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
var normalView = L.tileLayer(osmUrl, {styleId: 997, attribution: osmAttributes, maxZoom: 18 });
...

//define overlay layers
var markersLayer = new L.layerGroup();
var linesLayer = new L.layerGroup();
...

//create MAP with default base and overlay layers
var map = L.map('map', {
layers: [normalView, markersLayer]
}).setView([45.2516700, 19.8369400], 12);

//add layers to the base and overlay
var baseMaps = {
    "Normal view": normalView,
    "Night view": nightView,
    "MapQuest layer": mapQuest
};

var overlayMaps = {
    "Markers": markersLayer,
    "Lines": linesLayer,
    "3D layer": osmbView
};

//add layer control to the map
L.control.layers(baseMaps, overlayMaps).addTo(map);
Marko Letic
  • 2,460
  • 2
  • 28
  • 34
  • The aforementioned snippet, this is from the documentation and exactly what I used as a starting point to create the JSFiddle. The only difference I can see is the new keyword in front of the new keyword in front of the basemap layers, which I tried after seeing this response. The behavior is exactly the same...no change. – knu2xs Jul 17 '14 at 16:17
  • No, you didn't try what I said. You need to create 2 layers, one base and one overlay layer and than to add them with: L.control.layers(baseMaps, overlayMaps).addTo(map); I edited your JSFiddle: http://jsfiddle.net/FH9VF/11/ – Marko Letic Jul 18 '14 at 07:53
  • Thank you for clarifying...interacting with this layer though, is not what is needed. It just needs to be visible all the time, but not controllable. Would this be best accomplished using an event listener for the layer control baselayerchange event and add the hydro layer every time the basemap layer is changed, or is there a better way to accomplish this? – knu2xs Jul 18 '14 at 13:57