leaflegend is a package to extend the customization of legends for the leaflet package in R. The addLegend function provides some great out of the box legends based on the internal palette functions, but styling of the legend components has to be done with external css code as in this example.

leaflegend allows the user to add images to legends, style the labels of the legend items, change orientation of the legend items, use different symbologies, and style axis ticks. Syntax and style is consistent with the leaflet package to lower the mental overhead for new users and the legends are outputs from leaflet::addControl to ensure interoperability.

Custom Images in Legends

Image files already are supported for mapping using the icon series of functions per documentation. addLegendImage accepts png, jpg, and svg data URIs and encodes and embeds them into the legend.

library(leaflet)
library(leaflegend)
data("quakes")
# from https://rstudio.github.io/leaflet/markers.html
quakes1 <- quakes[1:10,]
leafIcons <- icons(
  iconUrl = ifelse(quakes1$mag < 4.6,
                   "http://leafletjs.com/examples/custom-icons/leaf-green.png",
                   "http://leafletjs.com/examples/custom-icons/leaf-red.png"
  ),
  iconWidth = 38, iconHeight = 95,
  iconAnchorX = 22, iconAnchorY = 94,
  shadowUrl = "http://leafletjs.com/examples/custom-icons/leaf-shadow.png",
  shadowWidth = 50, shadowHeight = 64,
  shadowAnchorX = 4, shadowAnchorY = 62
)

leaflet(data = quakes1, width = '100%') %>% addTiles() %>%
  addMarkers(~long, ~lat, icon = leafIcons) %>%
  addLegendImage(images = c("http://leafletjs.com/examples/custom-icons/leaf-green.png",
                            "http://leafletjs.com/examples/custom-icons/leaf-red.png"),
                 labels = c('Green', 'Red'),width = 38, height = 95,
                 orientation = 'vertical',
                 title = htmltools::tags$div('Leaf',
                                             style = 'font-size: 24px; text-align: center;'),
                 position = 'topright')

Creating SVG Map Symbols

A helper function is provided to create svg data URIs for commonly used symbols – rect, circle, triangle, plus, cross, star and stadium. Beyond the named arguments for styling the symbol, you can use ... to pass arguments to modify the svg. I would recommend taking a look at MDB Web Docs to see all the available options.

redx <- makeSymbol('cross', width = 100, height = 100, color = 'black', fillColor = 'red',
           opacity = .7, fillOpacity = .5)
htmltools::img(src = redx)

Images on disk can be mixed with the symbols and displayed. To make your own symbol, create a character string with data:image/svg+xml,<svg>...</svg> and add the class ‘svgURI’.

leaflet(data = quakes1, width = '100%') %>% addTiles() %>%
  addMarkers(~long, ~lat, icon = leafIcons) %>%
  addLegendImage(images = list("http://leafletjs.com/examples/custom-icons/leaf-green.png",
                               "http://leafletjs.com/examples/custom-icons/leaf-red.png",
                               redx),
                 labels = c('Green', 'Red', 'Cross'), 
                 width = c(38, 38, 40), 
                 height = c(95, 95, 40),
                 orientation = 'vertical',
                 title = htmltools::tags$div('Leaf',
                                             style = 'font-size: 24px; text-align: center;'),
                 position = 'topright')

The map symbols can be used on leaflet maps as well. Create a list of the items and create them as icons as you would for image files or from icon libraries.

shapes <- c('rect', 'circle', 'triangle', 'plus', 'cross', 'star')
symbols <- setNames(Map(f = makeSymbol
               ,shape = shapes
               ,fillColor = c('blue', 'red', 'green', 'yellow', 'orange', 'purple')
               ,color = 'black'
               ,opacity = 1
               ,fillOpacity = .5
               ,height = 24
               ,width = 24
               ,'stroke-width' = 2), shapes)
quakes[['symbol']] <- sample(shapes, nrow(quakes), replace = TRUE)

leaflet(data = quakes[sample(seq_len(nrow(quakes)), 25),], width = '100%') %>% addTiles() %>%
  addMarkers(
    ~ long,
    ~ lat,
    icon = ~ icons(
      iconUrl = symbols[symbol],
      iconWidth = 20,
      iconHeight = 20
    )
  ) %>%
  addLegendImage(
    images = symbols,
    labels = shapes,
    width = 50,
    height = 50,
    orientation = 'vertical',
    title = htmltools::tags$div('Symbol',
                                style = 'font-size: 24px; text-align: center;'),
    position = 'topright'
  )

Update: Requires leaflegend >= 1.0.0

shapeColorPal <- colorFactor(c('blue', 'red', 'green', 
                               'yellow', 'orange', 'purple'),
                             shapes)
leaflet(data = quakes[sample(seq_len(nrow(quakes)), 25),], width = '100%') %>% 
  addTiles() %>%
  addSymbols(
    lng = ~long,
    lat = ~lat,
    values = ~symbol, color = 'black', 
    fillColor = ~shapeColorPal(symbol),
    fillOpacity = .5,
    width = 24,
    height = 24
  ) %>%
  addLegendSymbol(
    pal = shapeColorPal,
    values = ~symbol,
    color = 'black',
    fillOpacity = .5,
    width = 50,
    height = 50,
    orientation = 'vertical',
    title = htmltools::tags$div('Symbol',
                                style = 'font-size: 24px; text-align: center;'),
    position = 'topright'
  )

Customizing Leaflet Legends with Palettes

The addLegend* functions take palettes generated from the leaflet package and uses them to create legends with greater flexibility. For instance, using differently symbology for points is possible by specifying a different shape. You can control the opacity of the outline and fill so that it matches what is displayed on the map. Position the legend elements to be horizontal or vertical and control the text styling of the title and the label elements.

binPal <- colorBin('Set1', quakes$mag)
symbols <- lapply(binPal(quakes$mag)
                  ,makeSymbol
                  ,shape = 'triangle'
                  ,opacity = 1
                  ,fillOpacity = .5
                  ,height = 24
                  ,width = 24
                  ,'stroke-width' = 1)
leaflet(width = '100%') %>%
  addTiles() %>%
  addMarkers(
    data = quakes,
    lat = ~ lat,
    lng = ~ long,
    icon = ~icons(
      iconUrl = symbols,
      iconWidth = 10,
      iconHeight = 10
    )
  ) %>%
  addLegendBin(
    pal = binPal,
    values = quakes$mag,
    position = 'bottomleft',
    title = 'horizontal',
    shape = 'triangle',
    opacity = 1,
    fillOpacity = .2,
    labelStyle = 'font-size: 18px; font-weight: bold;',
    orientation = 'horizontal',
    layerId = 'horizontal'
  ) %>%
  addLegendBin(
    pal = binPal,
    values = quakes$mag,
    position = 'bottomright',
    title = 'vertical',
    shape = 'triangle',
    opacity = 1,
    fillOpacity = .2,
    orientation = 'vertical',
    layerId = 'vertical'
  ) %>%
  addLegend(pal = binPal,
            values = quakes$mag,
            title = 'addLegend',
            layerId = 'addLegend')

[CRAN] [github]