How to add titles to a layer control box in a Leaflet map in R

GIS R Leaflet

28 May, 2021



tl;dr
htmlwidgets::onRender(map, "
    function() {
        $('.leaflet-control-layers-overlays').prepend('');
        $('.leaflet-control-layers-list').prepend('');
    }
")

Minimal example code here.

Introduction

Leaflet maps have this concept of layer control, which you can use to show or hide map layers (like points or markers, or shapes). The layers are controlled by a box that's usually in the top-right corner of the map. The layer levels are labelled, but there's no parameter that allows you to add a title to the control box (neither for the base layers part, or the overlay part). This is somewhat analogous to a title in a legend, so it's a pretty useful thing to be able to add. This brief post shows how you can add a title (or two) to a layer control box, using some JavaScript in a Leaflet map made in R.

Doing the thing

We're going to take advantage of the htmlWidgets::onRender function to insert some JavaScript into the map after it's been rendered. You can see an example of another use case of that in the docs.

The layer control box can have two components: One for the base layer, and one for the overlays. The base layer defines the tiles used by the map, while the overlays can be any typical GIS objects, like shapes, lines, markers, and so on. The base layer and the overlay components are accessed by the following classes, respectively:

.leaflet-control-layers-list
.leaflet-control-layers-overlays

The strategy (first described by Saurabh Yadav here) is simply to prepend the title to those classes. The example that Saurabh gave was this:

$(".leaflet-control-layers-overlays").prepend("");

That's pretty much exactly what we're going to do, and we'll insert it with htmlWidgets::onRender like this:

htmlwidgets::onRender(map, "
    function() {
        $('.leaflet-control-layers-overlays').prepend('');
    }
")

(map is our Leaflet map object. I try to do everything I can in a pipe, so I'll usually be piping the map object into the onRender call.)

Here's a minimal working example. We're plotting the location of earthquakes off Fiji (using the base R quakes dataset), and we'll give the user the option of showing or hiding the quakes, as well as the option of selecting the base map to use. For the former option, that of showing or hiding the quakes, we'll insert a title by prepending it to the .leaflet-control-layers-overlays class. The latter option, asking which base map to display, will have a title supplied by prepending a label to the .leaflet-control-layers-list class. A couple of notes:

library(leaflet)

leaflet(quakes) %>%
    addTiles(group = "OpenStreetMap") %>%
    addProviderTiles(providers$CartoDB.Positron, group = "Positron") %>%
    addCircles(~long, ~lat, group = "Show quakes") %>%
    addLayersControl(
        baseGroups = c("OpenStreetMap", "Positron"),
        overlayGroups = "Show quakes",
        options = layersControlOptions(collapsed = FALSE)) %>%
    htmlwidgets::onRender("
        function() {
            $('.leaflet-control-layers-overlays').prepend('');
            $('.leaflet-control-layers-list').prepend('');
        }
    ")

Here's a Shiny app with the minimal example on my server.

Enjoy.

References



0 comments

Leave a comment