添加标签页后Shiny仪表盘内Leaflet地图同步失效问题
解决shinydashboard多标签页下Leaflet地图同步失效问题
问题描述
在shinydashboard中添加多标签页后,使用leaflet.extras2的addLeafletsync实现两张Leaflet地图同步的功能失效,但仅保留单个Maps标签页时功能正常。可复现代码如下:
library(shiny) library(leaflet) library(leaflet.extras2) library(shinydashboard) ui <- dashboardPage( dashboardHeader(title = "My app"), dashboardSidebar( width = 250, sidebarMenu(id = "pages", menuItem("Overview", tabName = "Overview"), ##### LINE 1 menuItem("Maps", tabName = "Maps"))), dashboardBody( tabItems( tabItem(tabName = "Overview", h4(HTML("Toy example"))), ##### LINE 2 tabItem( tabName = "Maps", fluidRow( column(6, leafletOutput("map1")), column(6, leafletOutput("map2")), actionButton("add_markers", "Add markers")))))) server <- function(input, output, session){ output$map1 <- renderLeaflet({ leaflet() |> addTiles() |> setView(lng = 0, lat = 52, zoom = 6) }) output$map2 <- renderLeaflet({ leaflet() |> addTiles() |> setView(lng = 0, lat = 52, zoom = 6) }) leafletProxy("map1") |> addLeafletsync(c("map1","map2")) observeEvent(input$add_markers, { for (m in c("map1","map2")){ lat <- runif(1, 51, 52) lng <- runif(1, -1, 1) leafletProxy(m) |> addMarkers(lng = lng, lat = lat) } }) } shinyApp(ui = ui, server = server)
问题原因
服务器启动时直接执行addLeafletsync,但此时Maps标签页未被激活,两张地图的DOM元素尚未渲染完成,导致同步绑定无法成功挂载到地图实例上。
解决方案
通过监听标签页切换事件,确保在Maps标签页被激活、地图渲染完成后再执行同步绑定操作。修改服务器部分代码如下:
server <- function(input, output, session){ output$map1 <- renderLeaflet({ leaflet() |> addTiles() |> setView(lng = 0, lat = 52, zoom = 6) }) output$map2 <- renderLeaflet({ leaflet() |> addTiles() |> setView(lng = 0, lat = 52, zoom = 6) }) # 监听标签页切换,进入Maps标签页时初始化同步 observeEvent(input$pages, { if(input$pages == "Maps"){ # 延迟执行确保地图DOM完全加载 invalidateLater(100, session) leafletProxy("map1") |> addLeafletsync(c("map1","map2")) } }, ignoreInit = FALSE) observeEvent(input$add_markers, { for (m in c("map1","map2")){ lat <- runif(1, 51, 52) lng <- runif(1, -1, 1) leafletProxy(m) |> addMarkers(lng = lng, lat = lat) } }) }
修改说明
- 利用
sidebarMenu的id="pages"监听标签页切换事件,当切换到Maps标签页时执行同步绑定。 - 添加
invalidateLater(100, session)延迟执行,确保地图的DOM元素完全渲染完成后再挂载同步逻辑,避免因DOM未就绪导致绑定失败。 ignoreInit = FALSE确保app启动时如果默认显示Maps标签页,同步也能正常初始化。
内容的提问来源于stack exchange,提问作者user2602640
相关产品推荐
相关产品推荐

