【问题标题】:How to save a leaflet map in Shiny如何在 Shiny 中保存传单地图
【发布时间】:2017-10-30 18:42:39
【问题描述】:

this 问题之后,我希望将传单地图保存并下载为 png 或 jpeg 图像。我有以下代码,但我不断收到错误消息。

ui <- fluidPage(
  leafletOutput("map"),
  downloadButton("dl")
)

server <- function(input, output, session) {
  output$map <- renderLeaflet({
    leaflet() %>% 
      addTiles()
  })

  output$dl <- downloadHandler(
    filename = "map.png",

    content = function(file) {
      mapshot(input[["map"]], file = file)
    }
  )
}

shinyApp(ui = ui, server = server)

我尝试下载(通过单击按钮)时遇到的错误是

Warning: Error in system.file: 'package' must be of length 1
Stack trace (innermost first):
    65: system.file
    64: readLines
    63: paste
    62: yaml.load
    61: yaml::yaml.load_file
    60: getDependency
    59: widget_dependencies
    58: htmltools::attachDependencies
    57: toHTML
    56: <Anonymous>
    55: do.call
    54: mapshot
    53: download$func [#11]
     4: <Anonymous>
     3: do.call
     2: print.shiny.appobj
     1: <Promise>
Error : 'package' must be of length 1

如果您能告诉我如何使用 leafletProxy 来实现此功能,则可以加分。

【问题讨论】:

    标签: r shiny leaflet r-leaflet


    【解决方案1】:

    概述

    由于'leaflet' maps 是交互式的,mapview::mapshot() 函数中使用的传单对象也必须是交互式的。考虑到这一点,用户可以在Shiny app 中保存他们的版本的传单地图。

    # install necessary packages
    install.packages( c( "shiny", "leaflet", "mapview" ) )
    
    # load necessary packages
    library( shiny )
    library( leaflet )
    library( mapview )
    
    ui <- fluidPage(
      leafletOutput( outputId = "map"),
      downloadButton( outputId = "dl")
    )
    
    server <- function(input, output, session) {
      
      # Create foundational leaflet map
      # and store it as a reactive expression
      foundational.map <- reactive({
        
        leaflet() %>% # create a leaflet map widget
          
          addTiles( urlTemplate = "https://{s}.tile.openstreetmap.se/hydda/base/{z}/{x}/{y}.png" ) # specify provider tile and type
        
      }) # end of foundational.map()
      
      # render foundational leaflet map
      output$map <- leaflet::renderLeaflet({
        
        # call reactive map
        foundational.map()
        
      }) # end of render leaflet
      
      # store the current user-created version
      # of the Leaflet map for download in 
      # a reactive expression
      user.created.map <- reactive({
        
        # call the foundational Leaflet map
        foundational.map() %>%
          
          # store the view based on UI
          setView( lng = input$map_center$lng
                   ,  lat = input$map_center$lat
                   , zoom = input$map_zoom
          )
        
      }) # end of creating user.created.map()
      
      
      
      # create the output file name
      # and specify how the download button will take
      # a screenshot - using the mapview::mapshot() function
      # and save as a PDF
      output$dl <- downloadHandler(
        filename = paste0( Sys.Date()
                           , "_customLeafletmap"
                           , ".pdf"
        )
        
        , content = function(file) {
          mapshot( x = user.created.map()
                   , file = file
                   , cliprect = "viewport" # the clipping rectangle matches the height & width from the viewing port
                   , selfcontained = FALSE # when this was not specified, the function for produced a PDF of two pages: one of the leaflet map, the other a blank page.
          )
        } # end of content() function
      ) # end of downloadHandler() function
      
    } # end of server
    
    # run the Shiny app
    shinyApp(ui = ui, server = server)
    
    # end of script #
    

    最终结果

    运行 Shiny 应用后,在新窗口中打开该应用。

    进入浏览器后,点击Download。大约需要 3 秒。

    单击Download 后,您将立即看到一个PDF 文件,无论您下载的文件存储在计算机上的何处。

    参考文献

    我的想法来自以下帖子:

    【讨论】:

    • 这太棒了!非常有帮助。您还可以使用 input$map_center$lng 和 input$map_center$lat 获取地图中心。所以你可以只使用 setView(lng = input$map_center$lng, lat = input$map_center$lat, zoom = input$map_zoom)
    • 绝对!我通常将服务器上的renderPrint({reactiveValuesToList(input)}) 和用户界面上的verbatimTextOutput 结合起来,以查看所有可用的输入。那是我看到input$map_center 选项的地方
    • @blondeclover - 现在这太棒了!哈哈,这正是我想要的:所有可用输入的列表。谢谢你给我看这个。我添加了一个屏幕截图和打印这些输入事件所需的代码。我希望其他人发现这对在 Shiny 应用程序中开发他们的传单地图很有用!
    • 我想保存一张传单地图,其中包含通过 leaflet.extras 包中的 addDrawToolbar 绘制的形状和线条。我已经使用了您的答案,但没有用。你也可以看看吗? stackoverflow.com/questions/53650039/….
    • @mpetric - 没问题!就您的情况而言,我不确定为什么当您发布 Shiny 应用程序时,下载按钮会返回空白 HTML 而不是 PDF 文件。我的建议是你做一个可重现的例子,链接到这个解决方案,然后提出一个新问题。由于这篇文章已经发布了将近 3 年,因此发布一个更新的问题可能对 R 社区有好处。
    【解决方案2】:

    这可能会有所帮助:

      server <- function(input, output, session) {
    
        map <- reactiveValues(dat = 0)
    
          output$map <- renderLeaflet({
            map$dat <- leaflet() %>% 
              addTiles()
          })
    
          output$dl <- downloadHandler(
            filename = "map.png",
    
            content = function(file) {
              mapshot(map$dat, file = file)
            }
          )
        }
    

    【讨论】:

    • 感谢您的建议,但这对我不起作用
    • 这段代码对你有用吗? library(mapview) m % addTiles() mapshot(m, file = "map.png")
    • 啊 - 它正在工作,只是需要一段时间才能运行。有趣的是,它只是下载了一个灰屏......
    • 然后尝试运行webshot::install_phantomjs(),然后运行上面的代码。希望它会起作用。
    猜你喜欢
    • 2016-05-24
    • 2019-05-08
    • 2016-07-29
    • 2017-04-27
    • 2021-06-18
    • 2021-08-15
    • 2018-06-04
    • 2017-02-08
    • 1970-01-01
    相关资源
    最近更新 更多