tmap_mode("view")
tm_shape(your_data) +
tm_polygons(fill = "your_variable",
hover = "name",
popup.vars = c("name", "your_variable")) +
tm_basemap("CartoDB.Positron")Session 12: Putting it all together: building a complete interactive map application
Day 1 — tmap foundations
ttm()tm_legend(), tm_pos()group, group.controlDay 2 — Interactive maps
hover, popup.vars, idrtm()tm_polygons_3d(), WebGLDay 3 — Shiny
tmap_save(), HTML, animationsrenderTmap(), tmapProxy(), map eventsData (sf, terra, stars)
↓
tmap specification (tm_shape + layers)
↓
Mode choice:
"plot" → static PNG/PDF via tmap_save()
"view" → interactive Leaflet HTML
"maplibre" → interactive MapLibre GL HTML
↓
Output:
Standalone HTML → tmap_save(..., ".html")
Shiny app → renderTmap() + tmapProxy()
Quarto / R Markdown → embed in code chunk
A donut map (Tennekes & Chen 2021) is a method for visualising origin-destination flows:
Built with tmap, tmap.networks, tmap.glyphs, and sfnetworks.
tm_edges() draws the half-lines — lwd encodes total flow, col encodes destination categorytm_donuts() places glyphs at each node — size encodes total jobs, parts encode the breakdown by origin"Flows", "Donuts") let users toggle each layer independentlyhover and popup.vars make both layers interactiveA Shiny wrapper adds interactive controls:
eventReactive), avoiding expensive re-renders on every slider movebuild_map() helper keeps the tmap logic separate from the Shiny boilerplateMore tmap features
tm_facets()) — small multiplestm_animate(), tmap_animation()) — time-lapse mapstm_legend_combine(), bivariate legendstm_inset() — embed a zoomed-in detail or ggplot2 charttmap extensions
tmap.cartogram — contiguous, non-contiguous, and Dorling cartogramstmap.glyphs — donut and flower glyphs per featuretmap.networks — sfnetwork / igraph visualisationRelated packages
mapgl — direct access to Mapbox/MapLibrebslib — modern Shiny UI themingYou have worked through three days of tmap. Now bring it all together with your own data.
The assignment has two parts:
Use the rest of this session to work on it — ask questions, explore, experiment.
Build an interactive tmap map of your own spatial data. Aim to include:
fill, size, or col)hover) and/or popups (popup.vars)Save it: tmap_save(m, "my_map.html")
Wrap your map in a Shiny app with at least one input widget.
Suggested structure:
If you finish early, try adding one of these:
tmapProxy() — update only the fill variable without re-rendering the whole mapverbatimTextOutput or tableOutputtm_minimap() — add a locator minimaptmap_mode("maplibre") and see how the map changes (set before shinyApp())downloadButton that calls tmap_save() to let users download the map as HTML"plot" to "view" is often just one function calltmap.mapgl unlocks GPU-accelerated rendering and 3D