Skip to content

The Leaflet package includes functions to show and hide map layers. You can allow users to decide what layers to show and hide, or programmatically control the visibility of layers using server-side code in Shiny.

In both cases, the fundamental unit of showing/hiding is the group.

Understanding Groups

A group is a label given to a set of layers. You assign layers to groups by using the group parameter when adding the layers to the map.

leaflet() %>%
  addTiles() %>%
  addMarkers(data = coffee_shops, group = "Food & Drink") %>%
  addMarkers(data = restaurants, group = "Food & Drink") %>%
  addMarkers(data = restrooms, group = "Restrooms")

Many layers can belong to same group. But each layer can only belong to zero or one groups (you can’t assign a layer to two groups).

Groups vs. Layer IDs

Groups and Layer IDs may appear similar, in that both are used to assign a name to a layer. However, they differ in that layer IDs are used to provide a unique identifier to individual markers and shapes, etc., while groups are used to give shared labels to many items.

You generally provide one group value for the entire addMarkers() call, and you can reuse that same group value in future add*() calls to add to that group’s membership (as in the example above).

layerId arguments are always vectorized: when calling e.g. addMarkers() you need to provide one layer ID per marker, and they must all be unique. If you add a circle with a layer ID of "foo" and later add a different shape with the same layer ID, the original circle will be removed.

Interactive Layer Display

You can use Leaflet’s layers control feature to allow users to toggle the visibility of groups.

outline <- quakes[chull(quakes$long, quakes$lat),]

map <- leaflet(quakes) %>%
  # Base groups
  addTiles(group = "OSM (default)") %>%
  addProviderTiles(providers$Stadia.StamenToner, group = "Toner") %>%
  addProviderTiles(providers$Stadia.StamenTonerLite, group = "Toner Lite") %>%
  # Overlay groups
  addCircles(~long, ~lat, ~10^mag/5, stroke = FALSE, group = "Quakes") %>%
  addPolygons(data = outline, lng = ~long, lat = ~lat,
    fill = FALSE, weight = 2, color = "#FFFFCC", group = "Outline") %>%
  # Layers control
  addLayersControl(
    baseGroups = c("OSM (default)", "Toner", "Toner Lite"),
    overlayGroups = c("Quakes", "Outline"),
    options = layersControlOptions(collapsed = FALSE)
  )
map

addLayersControl() distinguishes between base groups, which can only be viewed one group at a time, and overlay groups, which can be individually checked or unchecked.

Although base groups are generally tile layers, and overlay groups are usually markers and shapes, there is no restriction on what types of layers can be placed in each category.

Only one layers control can be present on a map at a time. If you call addLayersControl() multiple times, the last call will win.

Programmatic Layer Display

You can use showGroup() and hideGroup() to show and hide groups from code. This mostly makes sense in a Shiny context with leafletProxy, where perhaps you might toggle group visibility based on input controls in a sidebar.

You can also use showGroup()/hideGroup() in conjunction with addLayersControl() to set which groups are checked by default.

map %>% hideGroup("Outline")

Finally, you can remove the layers in a group using clearGroup(). Note that this doesn’t just remove the layers from the group, it also removes them from the map. (It does not, however, remove the group itself from the map; it still exists, but is empty.)

With Marker Clusters

If markers are added to different groups, and when using marker clustering as described in the marker page, leaflet will generate different sets of clusters for different groups. This allows showing/hiding of marker clusters belonging to a group independently of other marker clusters in other groups.


quakes <- quakes %>%
  dplyr::mutate(mag.level = cut(mag,c(3,4,5,6),
                                labels = c('>3 & <=4', '>4 & <=5', '>5 & <=6')))

quakes.df <- split(quakes, quakes$mag.level)

l <- leaflet() %>% addTiles()

names(quakes.df) %>%
  purrr::walk( function(df) {
    l <<- l %>%
      addMarkers(data=quakes.df[[df]],
                          lng=~long, lat=~lat,
                          label=~as.character(mag),
                          popup=~as.character(mag),
                          group = df,
                          clusterOptions = markerClusterOptions(removeOutsideVisibleBounds = FALSE),
                          labelOptions = labelOptions(noHide = FALSE,
                                                       direction = 'auto'))
  })

l %>%
  addLayersControl(
    overlayGroups = names(quakes.df),
    options = layersControlOptions(collapsed = FALSE)
  )