Always set tmap_mode()beforeshinyApp() — not inside server or renderTmap()
It is not possible to switch modes from within a Shiny app
Shiny integration is implemented for all modes, also maplibre and mapbox
# ✅ correcttmap_mode("view")shinyApp(ui, server)# ❌ does not work as expectedserver <-function(input, output) { output$map <-renderTmap({tmap_mode("view") # has no effect heretm_shape(World) +tm_polygons(fill ="HPI") })}
Update the map with tmapProxy()
In the previous example, the map will rerender after selecting another variable
Better is to update the map, which will retain the current view
Only useful in view mode
Example with tmapProxy()
world_vars <-setdiff(names(World), c("iso_a3", "name", "sovereignt", "geometry"))tmap_mode("view")shinyApp(ui =fluidPage(tmapOutput("map", height ="600px"), selectInput("var", "Variable", world_vars)), server <-function(input, output, session) { output$map <-renderTmap({tm_shape(World) +tm_polygons(fill = world_vars[1], id ="iso_a3", zindex =401) })observe({ var <- input$vartmapProxy("map", session, {tm_remove_layer(401) +tm_shape(World) +tm_polygons(fill = var, id ="iso_a3", zindex =401) }) }) }, options =list(launch.browser=TRUE))
Reacting to map events
Map inputs available in Shiny
When a tmap map is rendered with renderTmap(), Shiny automatically exposes these inputs (here for tmapOutput("map")):
Input
What it contains
input$map_shape_click
Clicked feature: id, coordinates
input$map_shape_mouseover
Feature under cursor
input$map_shape_mouseout
Feature cursor just left
input$map_bounds
Current map bounding box
input$map_center
Current map centre (lat/lon)
input$map_zoom
Current zoom level
input$map_groups
Active layer groups
These are Leaflet ("view" mode) specific
The id argument and click events
The id column from the layer function is returned as input$map_shape_click$id when a feature is clicked:
# e.g. if tmapOutput("map"):input$map_shape_click$id # the id value of the clicked featureinput$map_shape_click$lat # latitude of clickinput$map_shape_click$lng # longitude of click
Example: show country info on click
tmap_mode("view")ui <-fluidPage(tmapOutput("map"),verbatimTextOutput("info"))server <-function(input, output, session) { output$map <-renderTmap({tm_shape(World) +tm_polygons(fill ="HPI",popup.vars =c("name", "HPI", "life_exp"),id ="iso_a3") # id at layer level }) output$info <-renderText({print(input$map_shape_click) clicked <- input$map_shape_click$idif (is.null(clicked)) return("Click a country on the map") row <- World[World$iso_a3 == clicked, ]paste0(row$name, " — HPI: ", round(row$HPI, 1)) })}shinyApp(ui, server)
Example: pan to selected country
Use input$map_zoom and leafletProxy() / tmapProxy() to pan the map when a user selects a country from a dropdown:
tmap_mode("view")ui <-fluidPage(selectInput("country", "Go to country",choices =sort(World$name)),tmapOutput("map"))server <-function(input, output, session) { output$map <-renderTmap({tm_shape(World) +tm_polygons(fill ="HPI", id ="name") # id at layer level })observe({ sel <- World[World$name == input$country, ] bb <- sf::st_bbox(sel) leaflet::leafletProxy("map") |> leaflet::fitBounds(bb[["xmin"]], bb[["ymin"]], bb[["xmax"]], bb[["ymax"]]) })}shinyApp(ui, server)