我有一个带有正在下载的地图的应用程序。我很困惑为什么下载的图像的空间范围/缩放与屏幕上显示的图像如此不同。寻找任何建议以使输出尽可能接近应用程序本身显示的地图......
library(shiny)
library(dplyr)
library(leaflet)
library(mapview)
library(ggplot2)
# reproducible example of the shiny app
df <- structure(list(Lon = c(-111.584650079555, -112.17670350598, -111.585725614472, -112.173232931394, -111.772792415394), Lat = c(41.7797872701221, 43.0098749960118, 41.7489995541869, 43.0096673539034, 42.1053681392244), Size = c(1:5)), row.names = c(NA, -5L), class = c("tbl_df", "tbl", "data.frame"))
server = function(input, output){
mymap <- reactive({
leaflet(df) %>%
setView(lng = -111.6, lat = 41.8, zoom = 8) %>%
addProviderTiles("Esri.WorldImagery", layerId = "basetile",
options = providerTileOptions(minZoom = 8, opacity = 0.75)) })
output$map <- renderLeaflet({
mymap() })
myfun <- function(map, df.in){
addCircleMarkers(map, data = df.in, lng = df.in$Lon, lat = df.in$Lat, radius = ~Size * 4, color = "red")
}
observe({
leafletProxy("map") %>% myfun(df)
})
# map that will be downloaded
mapdown <- reactive({
mymap() %>% myfun(df)
})
output$map_down <- downloadHandler(
filename = 'mymap.png',
content = function(file) {
owd <- setwd(tempdir())
on.exit(setwd(owd))
mapshot(mapdown(), file = file, cliprect = "viewport")
})}
ui <- fluidPage(
sidebarPanel(downloadButton('map_down', "Download map")),
mainPanel(leafletOutput("map")))
shinyApp(ui = ui, server = server)
按照@HubertL的建议,我花了很长的时间定义和重新定义视口大小(以及剪切选项),并尝试这个和那个,直到我最终发现我遇到的问题实际上只发生在
myfun
(实际制作绘图的函数)包括 fitBounds
,我需要用户能够在放大后导出图形。所以 - 我正在更新问题,代码显示在答案完美,除非包含fitBounds()
。如何在用户缩放后导出地图?
library(shiny)
library(dplyr)
library(leaflet)
library(mapview)
library(ggplot2)
df <- structure(list(Lon = c(-105.618, -105.505, -105.671, -105.737, -105.318, -105.747, -105.693, -105.126, -104.975, -105.297), Lat = c(23.851, 23.646, 24.085, 24.063, 23.378, 24.253, 23.965, 23.153, 23.127, 23.33), Size = c(4, 1, 4, 4, 2, 3, 4, 1, 1, 3)), row.names = c(NA, -10L), class = c("tbl_df", "tbl", "data.frame"))
ui <- navbarPage("My app", id = "nav",
fluidRow(column(width = 8,
leafletOutput("map", height = "800px")),
column(width = 4,
downloadButton('ExportMap', label = "Download the map"))))
myfun <- function(map, df.in, bounds){
latRng <- range(bounds$north, bounds$south)
lngRng <- range(bounds$east, bounds$west)
clearShapes(map) %>%
clearMarkers() %>%
clearControls() %>%
addCircleMarkers(data = df.in, lng = df.in$Lon, lat = df.in$Lat, radius = ~Size * 3) %>%
## This is the culprit - export works well if this is commented out
# fitBounds(min(lngRng), min(latRng), max(lngRng), max(latRng))
}
server <- function(input, output, session){
mymap <- reactive({
leaflet(df, options = leafletOptions(
attributionControl=FALSE)) %>%
setView(lng = -105.5, lat = 23.7, zoom = 8) %>%
addProviderTiles("Esri.WorldImagery", layerId = "basetile",
options = providerTileOptions(minZoom = 7, opacity = 0.75))
})
output$map <- renderLeaflet({
mymap()
})
bounds.calc <- reactive({
bounds <- input$map_bounds
zoom <- input$map_zoom
cen <- input$map_center
output <- list(bounds = bounds, zoom = zoom, center = cen)
})
observe({
leafletProxy("map") %>% myfun(df, bounds = bounds.calc()$bounds)
})
# map that will be downloaded
mapdown <- reactive({
mymap() %>% myfun(df, bounds = bounds.calc()$bounds)
})
output$ExportMap <- downloadHandler(
filename = 'mymap.png',
content = function(file) {
owd <- setwd(tempdir())
on.exit(setwd(owd))
mapshot(mapdown(), file = file, cliprect = "viewport", vwidth= 800, vheight = 600)
})}
shinyApp(ui = ui, server = server)
您可以为
vheight
设置 vwidth
和 webshot()
参数 :
mapshot(mapdown(), file = file, cliprect = "viewport", vwidth= 600, vheight = 400)