'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