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

添加标签页后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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 22:13:11