You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Shiny应用中含标记与过滤器的Leaflet地图下载报错求助

问题:Shiny中Leaflet地图下载报错webshot.js returned failure value: 1

需求:在Shiny应用中实现登录用户下载包含所有过滤器设置和标记的Leaflet地图视图,并将地图上传至服务器供登录用户按需下载。

遇到的错误:调用mapshot时始终报错:
Warning: Error in : webshot.js returned failure value: 1

示例代码

header <- dashboardHeader(title = "simple", uiOutput("logoutbtn"))

sidebar <- dashboardSidebar(uiOutput("sidebarpanel")) 
body <- dashboardBody(shinyjs::useShinyjs(), uiOutput("body"))
ui <- dashboardPage(header, sidebar, body, skin = "black")


credentials = data.frame(
  username_id = c("EEE"),
  passod      = sapply(c("123"), password_store),
  permission  = c("basic"), 
  stringsAsFactors = F
)

server <- function(input, output, session) {
  
  login = FALSE
  USER <- reactiveValues(login = login)
  
  observe({ 
    if (USER$login == FALSE) {
      if (!is.null(input$login)) {
        if (input$login > 0) {
          Username <- isolate(input$userName)
          Password <- isolate(input$passwd)
          if(length(which(credentials$username_id == Username)) == 1) { 
            pasmatch  <- credentials["passod"][which(credentials$username_id == Username),]
            pasverify <- password_verify(pasmatch, Password)
            if(pasverify) {
              USER$login <- TRUE
            } else {
              shinyjs::toggle(id = "nomatch", anim = TRUE, time = 1, animType = "fade")
              shinyjs::delay(3000, shinyjs::toggle(id = "nomatch", anim = TRUE, time = 1, animType = "fade"))
            }
          } else {
            shinyjs::toggle(id = "nomatch", anim = TRUE, time = 1, animType = "fade")
            shinyjs::delay(3000, shinyjs::toggle(id = "nomatch", anim = TRUE, time = 1, animType = "fade"))
          }
        } 
      }
    }    
  })
  
  output$logoutbtn <- renderUI({
    req(USER$login)
    tags$li(a(icon("fa fa-sign-out"), "Logout", 
              href="javascript:window.location.reload(true)"),
            class = "dropdown", 
            style = "background-color: #eee !important; border: 0;
                    font-weight: bold; margin:5px; padding: 10px;")
  })
  
  output$sidebarpanel <- renderUI({
    if (USER$login == TRUE ){ 
      sidebarMenu(
        menuItem("something", 
                 selectInput("region", label = "Choose Region:",
                             choices = c("All", "ee", "ww"), multiple = F),
                 selectInput("project", label = "Choose Project:",
                             choices = c("All", "Hsos 791", "jmmi 29", "camps 6"), multiple = F)),
        downloadButton("downloadData", "Download")
      )
    }
  })

  foundational.map <- reactive({
    leaflet(width = 1000, height = 500) %>% 
      addTiles() %>% # 替换无效的"spm"瓦片URL,用默认OpenStreetMap瓦片
      addPolygons(weight = 0.5, opacity = 1, color = "grey") # 修正color参数的引号问题
  })

  output$body <- renderUI({
    if (USER$login == TRUE ) {
      if(input$region == "ee"){ 
        if(input$project != "All") {
          location_input <- location_ee %>% filter(Project == input$project)
          foundational.map() %>%
            addCircleMarkers(data = location_input, 
                             lat = location_input$Latitude_y,
                             lng = location_input$Longitude_x,
                             radius = 2, col = location_input$color) %>%
            addLegend(position = "bottomright",  colors = c("blue", "orange", "green"),
                      labels = c("Hsos 791", "jmmi 29", "camps 6"), opacity = 1,
                      title = "Number of Coverage Area")
        } else {  
          foundational.map() %>%
            addCircleMarkers(data = location_ee, 
                             lat = location_ee$Latitude_y,
                             lng = location_ee$Longitude_x,
                             radius = 2, col = location_ee$color) %>%
            addLegend(position = "bottomright",  colors = c("blue", "orange", "green"),
                      labels = c("Hsos 791", "jmmi 29", "camps 6"), opacity = 1,
                      title = "Number of Coverage Area")
        }
      } else {
        foundational.map() # 处理其他region的情况
      }
    } else {
      loginpage # 假设loginpage是已定义的登录UI
    }
  })

  user.created.map <- reactive({
    req(input$map_center, input$map_zoom) # 确保地图交互参数存在
    foundational.map() %>%
      setView(lng = input$map_center$lng,
              lat = input$map_center$lat,
              zoom = input$map_zoom) %>%
      # 追加用户选择的过滤器对应的标记
      {
        if(input$region == "ee"){
          if(input$project != "All") {
            location_input <- location_ee %>% filter(Project == input$project)
            . %>% addCircleMarkers(data = location_input, 
                                   lat = location_input$Latitude_y,
                                   lng = location_input$Longitude_x,
                                   radius = 2, col = location_input$color)
          } else {
            . %>% addCircleMarkers(data = location_ee, 
                                   lat = location_ee$Latitude_y,
                                   lng = location_ee$Longitude_x,
                                   radius = 2, col = location_ee$color)
          }
        } else {
          .
        }
      } %>%
      addLegend(position = "bottomright",  colors = c("blue", "orange", "green"),
                labels = c("Hsos 791", "jmmi 29", "camps 6"), opacity = 1,
                title = "Number of Coverage Area")
  })

  output$downloadData <- downloadHandler(
    filename = paste0(Sys.Date(), "_Covarge_map.pdf"),
    content = function(file) {
      # 确保webshot和phantomjs正常
      if (!webshot::is_phantomjs_installed()) {
        webshot::install_phantomjs()
      }
      mapshot(x = user.created.map(),
              file = file,
              vwidth = 1000, # 和leaflet宽高匹配
              vheight = 500,
              zoom = 2, # 提升渲染清晰度
              selfcontained = TRUE)
    }
  )
}

修复方案

  • 依赖修复:运行webshot::install_phantomjs()重新安装PhantomJS,这个错误绝大多数是因为PhantomJS未正确安装或路径不可用。
  • 修正地图代码错误:
    • 示例中addTiles("spm")是无效的瓦片URL,替换为默认的addTiles()或合法的瓦片地址。
    • color = grey缺少引号,改为color = "grey"。
  • 调整mapshot参数:
    • 去掉cliprect = "viewport",改用明确的vwidth和vheight匹配Leaflet地图尺寸,避免视口识别错误。
    • 添加zoom参数提升渲染清晰度,设置selfcontained = TRUE确保资源打包完整。
  • 确保地图交互参数存在:在user.created.map()中用req(input$map_center, input$map_zoom)保证地图交互参数已加载,避免空值报错。
  • 权限检查:服务器上确保下载目录有读写权限,避免因无法写入文件导致报错。

内容的提问来源于stack exchange,提问作者HIXER

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 12:48:19