Edit: The original answer downloaded the map as rendered initially without taking user's interaction with the map into account. I updated my answer using this answer so the download reflects the map as it looks to the user.
- Use js to get the current size of the map
div
(as based on this and this)
- Update the map based on current zoom and map center
- Change the size of the screenshot using
vwidth
and vheight
Example based on this and this:
library(leaflet)
library(mapview)
library(shiny)
ui <- fluidPage(
# 1. js to get width/height of map div
tags$head(tags$script('
var dimension = [0, 0];
$(document).on("shiny:connected", function(e) {
dimension[0] = document.getElementById("map").clientWidth;
dimension[1] = document.getElementById("map").clientHeight;
Shiny.onInputChange("dimension", dimension);
});
$(window).resize(function(e) {
dimension[0] = document.getElementById("map").clientWidth;
dimension[1] = document.getElementById("map").clientHeight;
Shiny.onInputChange("dimension", dimension);
});
')),
leafletOutput("map"),
downloadButton("dl", "Download Map")
)
server <- function(input, output, session) {
# reactive values to store map
vals <- reactiveValues()
# create base map
output$map <- renderLeaflet({
vals$base <- leaflet() %>%
addProviderTiles(providers$OpenStreetMap) %>%
addTiles()
})
# create map as viewed by user
observeEvent({
input$map_zoom
input$map_center
}, {
vals$current <- vals$base %>%
setView(lng = input$map_center$lng,
lat = input$map_center$lat,
zoom = input$map_zoom)
}
)
# create download
output$dl <- downloadHandler(
filename = "map.png",
content = function(file) {
mapshot(vals$current, file = file,
# 2. specify size of map based on div size
vwidth = input$dimension[1], vheight = input$dimension[2])
}
)
}
shinyApp(ui = ui, server = server)