Using {leaflet} to make interactive maps in R

Making heavily customized interactive maps with {leaflet} in R

Maps
Open Street Maps
Interactive
Author

Aditya Dahiya

Published

May 11, 2025

Load packages

Code
pacman::p_load(
  sf,
  terra, 
  tidyterra,
  
  tidyverse,
  
  ggplot2,
  showtext,
  scales,
  ggtext,
  fontawesome,
  
  geodata,
  ggmap,
  leaflet
)

Visualization Parameters

Code
# Visualization Parameters

bts = 12 # Base Text Size
sysfonts::font_add_google("Saira Condensed", "body_font")
sysfonts::font_add_google("Saira", "title_font")
sysfonts::font_add_google("Saira Extra Condensed", "caption_font")
showtext::showtext_auto()
# A base Colour
bg_col <- "white"
seecolor::print_color(bg_col)

# Colour for highlighted text
text_hil <- "grey30"
seecolor::print_color(text_hil)

# Colour for the text
text_col <- "grey20"
seecolor::print_color(text_col)

theme_set(
  theme_minimal(
    base_size = bts,
    base_family = "body_font"
  ) +
    theme(
      text = element_text(
        colour = "grey30",
        lineheight = 0.3,
        margin = margin(0,0,0,0, "pt")
      ),
      plot.title = element_text(
        hjust = 0.5
      ),
      plot.subtitle = element_text(
        hjust = 0.5
      )
    )
)

# Caption stuff for the plot
sysfonts::font_add(
  family = "Font Awesome 6 Brands",
  regular = here::here("docs", "Font Awesome 6 Brands-Regular-400.otf")
)
github <- "&#xf09b"
github_username <- "aditya-dahiya"
xtwitter <- "&#xe61b"
xtwitter_username <- "@adityadahiyaias"
social_caption_1 <- glue::glue("<span style='font-family:\"Font Awesome 6 Brands\";'>{github};</span> <span style='color: {text_hil}'>{github_username}  </span>")
social_caption_2 <- glue::glue("<span style='font-family:\"Font Awesome 6 Brands\";'>{xtwitter};</span> <span style='color: {text_hil}'>{xtwitter_username}</span>")
plot_caption <- paste0(
  "**Data**:  ",
  "  |  **Code:** ", 
  social_caption_1, 
  " |  **Graphics:** ", 
  social_caption_2
  )
rm(github, github_username, xtwitter, 
   xtwitter_username, social_caption_1, 
   social_caption_2)

Creating Base Map of London with {leaflet}

Code
london_boroughs <- spData::lnd

london_outline_map <- spData::lnd |> 
  st_union()

map_centre <- st_centroid(london_outline_map) |> 
  st_coordinates() |> 
  as.numeric()

leaflet() |> 
  
  # Add Base Map 1
  addTiles(group = "Open Street Maps") |>
  
  # Add Base Map 2
  addProviderTiles(
    provider = providers$Esri.WorldImagery,
    group = "ESRI Satellite"
  ) |> 
  
  # Add Base Map 3
  addProviderTiles(
    provider = providers$CartoDB.Positron,
    group = "CartoDB Positron"
  ) |> 
  
  # Add Base Maps' Layers Control
  addLayersControl(
    baseGroups = c("Open Street Maps", "ESRI Satellite", 
                   "CartoDB Positron"),
    options = layersControlOptions(collapsed = TRUE)
  ) |>
  
  setView(
    lng = map_centre[1],
    lat = map_centre[2],
    zoom = 10
  ) |> 
  
  # Add an inset map
  addMiniMap(
    position = "bottomright",
    zoomLevelOffset = -4,
    toggleDisplay = TRUE
  ) |> 
  
  # Add Graticule, i.e. LAtitudes and Longitudes in map units
  addGraticule(
    interval = 0.1,
    style = list(weight = 0.5, color = "#7f7f7f"),
  ) |> 
  
  # Add measurement tool to map
  addMeasure(
    primaryLengthUnit = "kilometers",
    primaryAreaUnit = "acres",
    activeColor = "darkred",
    completedColor = "grey20"
  ) |> 
  
  # Add a Scale Bar
  addScaleBar(
    position = "bottomleft",
    options = scaleBarOptions(
      imperial = TRUE,
      metric = TRUE,
      maxWidth = 200
    )
  )
Figure 1: An interactive base map of London

Adding London Boroughs

Code
# RColorBrewer::brewer.pal(3, "Set3")
# RColorBrewer::brewer.pal.info
# cols4all::c4a_gui()
pal1 <- colorFactor("Spectral", london_boroughs$NAME)

leaflet() |> 
  
  setView(
    lng = map_centre[1],
    lat = map_centre[2],
    zoom = 9
  ) |> 

  # Add Base Map 3
  addProviderTiles(
    provider = providers$CartoDB.Positron,
    group = "CartoDB Positron"
  ) |> 
  
    # Add Base Map 2
  addProviderTiles(
    provider = providers$Esri.WorldImagery,
    group = "ESRI Satellite"
  ) |> 
  
  # Add Base Map 1
  addProviderTiles(
    provider = providers$OpenStreetMap,
    group = "Open Street Maps"
    ) |>
  
  # Add Base Maps' Layers Control
  addLayersControl(
    baseGroups = c("CartoDB Positron",
                   "Open Street Maps", 
                   "ESRI Satellite"
                   ),
    options = layersControlOptions(collapsed = TRUE)
  ) |>
  
  # Add an inset map
  addMiniMap(
    position = "bottomright",
    zoomLevelOffset = -4,
    toggleDisplay = TRUE,
    tiles = providers$CartoDB.Positron
  ) |> 
  
  # Add measurement tool to map
  addMeasure(
    primaryLengthUnit = "kilometers",
    primaryAreaUnit = "acres",
    activeColor = "darkred",
    completedColor = "grey20"
  ) |> 
  
  # Add a Scale Bar
  addScaleBar(
    position = "bottomleft",
    options = scaleBarOptions(
      imperial = TRUE,
      metric = TRUE,
      maxWidth = 100
    )
  ) |> 
  
  # Add London Boroughs Data
  addPolygons(
    data = london_boroughs,
    group = "Boroughs",
    
    # Edges
    color = "#262626",
    weight = 1,
    opacity = 0.8,
    
    # Inside
    fillColor = ~pal1(NAME),
    fillOpacity = 0.15,
    
    # Pop-up
    # label = ~NAME,
    popup = ~NAME
  ) |> 
  
  # Add Base Maps' Layers Control
  addLayersControl(
    baseGroups = c("CartoDB Positron",
                   "Open Street Maps", 
                   "ESRI Satellite" 
                   ),
    options = layersControlOptions(collapsed = TRUE)
  )
Figure 2: Interactive Map of London showing its Boroughs

Saving Static Plots

Code
ggsave(
  plot = g,
  filename = here::here("geocomputation", "images",
                        "leaflet_maps_1.png"),
  width = size_var,
  height = (5/4) * size_var,
  units = "px",
  bg = bg_col
)