Leaflet layer ordering - leaflet

I'm having problems about the layer ordering in leaflet.
I've followed this page
http://leafletjs.com/examples/layers-control.html
exact question would be... how can I reorder the layers (foreground background etc).
Lets say, one of my "base layers" is made of semi transparent tiles, and I want to see the "overlay layers" through my base layer (it should be at the foreground)
Depending on the page example, here is a snippet to explain more about the issue:
var baseMaps = {
"Minimal": minimal,
"Night View": midnight,
"My Custom Layer": customlayer
};
var overlayMaps = {
"Motorways": motorways,
"Cities": cities
};
In other words, I would like to know how to set "My Custom Layer" as the layer that will be at the foreground (above overlayMaps).
I've tried setting zindex values of layers, didn't help.
Thanks.

The layers control has two sets of layers, the set of base layers and the set of overlay layers. The overlay layers will be drawn on top of the base layers.
So generally, you'll want to add your transparent layer to the overlay layers.
The autoZIndex option, which is by default On, specifies that the control must assign z indices to each of its layers in the order in which they are added, and that means they'll be drawn in that order.
See http://leafletjs.com/reference.html#control-layers

Sets the zIndex of the tile layer.
setZIndex( <Number> zIndex )
myLayer1.setZIndex(4);
myLayer2.setZIndex(5);
Layer 2 over Layer 1

Related

Leaflet - Allow for switching to another base layer at higher than max zoom

I have 2 base layers (map and satellite) that users can switch between. The satellite layer's max zoom is higher by 2. I am using Leaflet's provided L.control.Layers() to manage the layers
var mapLayer = L.tileLayer('map-tiles.example.com/{z}/{x}/{y}.png', {
maxZoom: 18,
})
var satelliteLayer = L.tileLayer('satellite-tiles.example.com/{z}/{x}/{y}.png', {
maxZoom: 20,
})
var baseLayers = {
'Map': mapLayer,
'Satellite': satelliteLayer
}
var layerControls = L.control.layers(baseLayers).addTo(map);
If the user zooms to 19 or 20 in satellite view, he will not be able to switch back to the map layer (the radio button is disabled) until he zooms back to 18 or lower.
I want the user to be able to switch to the map layer even on zoom 19 or 20. And when the user switches to the map layer, the zoom will be set to 18.
Is there some way to achieve this with Leaflet's layer control? Or do I have to build a custom layer control?
Is there some way to achieve this with Leaflet's layer control?
Not with the default behaviour, no. If you check the relevant portion of the source code, you'll see that a L.Control.Layers always disables checkboxes/radio buttons when the layer is out of its min/maxzoom range.
Or do I have to build a custom layer control?
Yes, you can create your own subclass of L.Control.Layers disabling this functionality, replacing the relevant method with a function that does nothing:
L.Control.Layers.NeverDisable = L.Control.Layers.extend({
_checkDisabledLayers: function(){}
});
var myLayersControl = new L.Control.Layers.NeverDisable(
baselayers, overlayLayers, options);
myLayersControl.addTo(map);
You can check a working example in this plunkr.
An easy workaround to have your mapLayer selectionable on zooms 19-20 is to use the Tile Layer maxNativeZoom option at 18, and increase your maxZoom to 20.
Then if you still want to automatically decrease the zoom back to 18 when mapLayer is selected, use a listener on map "baselayerchange" event, check the map.getZoom() and modify it (map.setZoom(18)) if desired.

Mapbox: is it possible to update layer hierarchy?

I have a Mapbox with my own layers, says labels of towns and landmarks...
say I want to highlight one specific landmark and I want to move its z-index higher because otherwise, it would overlap with some other elements...
Can I use map.setLayoutProperty or is there anything else that I can do?
If I got your question correctly, you're looking for a way to change z-index of some layer above another layer. (not some feature above another feature). Here it the way:
https://www.mapbox.com/mapbox-gl-js/api/#map#movelayer
map.moveLayer(yourLandmarkLayerId, someAnotheLayerId);
If you would like just to move landmark layer to top of layer hierarchy:
map.moveLayer(yourLandmarkLayerId);
P.S. For moving layer, you should know it's ID:
var layers = map.getStyle().layers;
var layerId = layers[i].id;
For someone looking to do it on android, the simplest way to do it is to remove the layer and add it again above or below another layer. I do not find a better way:
/**
* Remove the target layer and add it again above the specific layer
*/
fun moveLayerAvobe(layer: Layer, breakpointLayerID: String, style: Style) {
// Remove Layer
style.removeLayer(layer)
// Add it again
style.addLayerAbove(layer, breakpointLayerID)
}

Mapbox GL JS: Trouble creating hover effects on mouseenter and mouseleave when layers are stacked (z-index)

I'm struggling to create a hover effect I believe should be pretty strait-forward and also a common use case for developers using mapbox gl js.
I have a map with 2 layers.
Layer 1 is a symbol layer that uses icons to mark points on the map.
Layer 2 is a symbol layer that shows a score (text) on top of the icon from layer 1.
Here is a video depicting the issue
I use filtering ala https://www.mapbox.com/mapbox-gl-js/example/hover-styles/ to listen for mouse events and hide and show Layer 2 when appropriate.
In my code I'm listening for mouseenter and mouseleave events on Layer 1. My problem is that as Layer 2 gets shown via a change in filter, it then causes a mouseleave event to get fired from Layer 1 because Layer 2 sits above Layer 1. As the mouse moves across Layer 2 the mouseenter and mouseleave events for Layer 1 get continually fired as the mouse event reaches through the lines of text of Layer 2 down to Layer 1. This causes flickering of Layer 2 as it gets shown and hidden.
Things I've tried:
I've attempted using the 'before' argument https://www.mapbox.com/mapbox-gl-js/example/geojson-layer-in-stack/
I've attempted to create a new layer (Layer 3) that sits on top of Layer 1 and Layer 2 containing a transparent icon of the same size as Layer 1 and listened for mouse events on Layer 3.
I've tried toggling the visibility of Layer 2 via setStyle (rather than using filters).
I've tried including the Layer 2 content as the text-field of Layer 1 and looking for a way to show-on-hover the text-field of a mapbox layer (couldn't figure out... is this possible?)
It seems that Mapbox gl js redraws the layer order when a layer is modified via filtering or style changes. The redraw seems to always place the affected layer on top!?
Any direction or advice would be greatly appreciated. Pretty stumped!!
Thanks for reading!
The mouseenter event can be problematic for several reasons, including the one you noticed.
A more reliable method is to use the mousemove event, and then directly call queryRenderedFeatures(). Something like:
var lastFeatureId;
map.on("mousemove", function (e) {
var fs = queryRenderedFeatures(e.point, { layers: ['myiconlayer']});
if (fs.length > 0) {
f = fs[0];
if (f.id !== lastFeatureId) {
lastFeatureId = f.id;
// some visual effect now that the mouse is over a new layer.
}
}
});

Mapbox GL - Can we add animation while filtering layers

I would like to do some animation while filters are being applied on layers. For example, I have 2 layers with circles drawn of different radius on some geo points. While I switch from one layer to other layer by setting filters using setFilter(), I want the transition on circle opacity for a smooth transition.
Please assist
You can use circle-opacity to enable/disable layers.
Set the opacity to 1 for active layers and to 0 for hidden layers.
I made a jsfiddle to illustrate this: https://jsfiddle.net/kmandov/kqey8y72/1/
Change the option from the select box to switch between the layers on the map.

User control of order of overlays in a Leaflet map

Is there a Leaflet plugin or example for letting the user control the display order of overlay layers in a map?
Turning layers on and off is working fine, but I'd like the user to be able to drag layer names within the layer control to set the Z order.
For Path class (Polygons, Polylines, etc.) there are methods 'bringToFront()' and 'bringToBack()'. You can't exactly set precise position in draw order, but iterating over layer list and calling 'bringToFront()' could be less time consuming, then re-drawing every layer (especialy if they are bigger).