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
相关产品推荐
相关产品推荐

