'Adding colormap legend to Folium map
I'm trying to make a map in Folium with multiple layers, each consisting of shaded areas (using GeoJSON) with colors given by a colormap. I'd like to add legends to my layers. I found a first solution here, but the problem with this solution were that the legend is fixed at the top right and more importantly, that it's always there. Instead, I'd like a legend that is only shown when the corresponding layer is shown.
Here is some example code that I tried (where m is my Folium map and cm1 and cm2 are color maps):
folium.GeoJson(data['Temp'],
name='Temp',
style_function=lambda x: {
'fillColor': cm1(x['properties']['Temp']),
'fillOpacity': 0.2,
'color' : None
},
highlight_function=lambda x: {'weight':3, 'color':'black'},
tooltip=folium.features.GeoJsonTooltip(fields=['Temp', 'Rain'],
labels=True,
sticky=True
), show=False).add_to(m)
folium.GeoJson(data['Rain'],
name='Rain',
style_function=lambda x: {
'fillColor': cm2(x['properties']['Rain']),
'fillOpacity': 0.2,
'color' : None
},
highlight_function=lambda x: {'weight':3, 'color':'black'},
tooltip=folium.features.GeoJsonTooltip(fields=['Temp', 'Rain'],
labels=True,
sticky=True
), show=False).add_to(m)
cm1.caption = 'Temp scale'
cm2.caption = 'Rain scale'
m.add_child(cm1)
m.add_child(cm2)
folium.LayerControl().add_to(m)
How can I change my code so that the legends are only shown when the corresponding layers are shown? (And if possible, how can I move the legends to the bottom left?)
Solution 1:[1]
If you only want to change the position of the LayerControl:
folium.map.LayerControl('topleft', collapsed=False).add_to(m)
if you know a bit of JavaScript you can change/manipulate e.g.: legend
Solution 2:[2]
The commented link gets most of the way to the solution! It just needs modification of the overlayadd
and overlayremove
events to layeradd
and layerremove
, so that the solution also works when you're using mutually-exclusive (overlay = False) layers.
# Adapted from: https://nbviewer.org/gist/BibMartin/f153aa957ddc5fadc64929abdee9ff2e
from branca.element import MacroElement
from jinja2 import Template
class BindColormap(MacroElement):
"""Binds a colormap to a given layer.
Parameters
----------
colormap : branca.colormap.ColorMap
The colormap to bind.
"""
def __init__(self, layer, colormap):
super(BindColormap, self).__init__()
self.layer = layer
self.colormap = colormap
self._template = Template(u"""
{% macro script(this, kwargs) %}
{{this.colormap.get_name()}}.svg[0][0].style.display = 'block';
{{this._parent.get_name()}}.on('layeradd', function (eventLayer) {
if (eventLayer.layer == {{this.layer.get_name()}}) {
{{this.colormap.get_name()}}.svg[0][0].style.display = 'block';
}});
{{this._parent.get_name()}}.on('layerremove', function (eventLayer) {
if (eventLayer.layer == {{this.layer.get_name()}}) {
{{this.colormap.get_name()}}.svg[0][0].style.display = 'none';
}});
{% endmacro %}
""") # noqa
# set up base map
map = folium.Map(tiles=None)
layer0 = folium.FeatureGroup(name='Base Map',overlay=True,control=False)
folium.TileLayer(tiles='OpenStreetMap').add_to(layer0)
layer0.add_to(map)
# imagine you've already defined two layers and associated colorbars
# call them layer1, colorbar1; layer2, colorbar2
map.add_child(colorbar1)
map.add_child(BindColormap(layer1,colorbar1))
map.add_child(colorbar2)
map.add_child(BindColormap(layer2,colorbar2))
folium.LayerControl(collapsed=False).add_to(test_map)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | evilmerc |