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

Shiny应用容器扩展后Leaflet地图重置按钮无法正确居中求助

Shiny Leaflet地图重置偏移问题的解决方案

问题背景

我开发的Shiny应用支持通过按钮折叠/显示数据表,以此扩展或恢复Leaflet地图的高度,但遇到了视口定位问题:

  • 应用刚启动时,移动地图后点击重置按钮,地图能正常居中;
  • 执行「Expand Map」(折叠数据表扩展地图)→「Show Table」(恢复数据表)操作后,点击重置按钮,地图会偏移到正确位置以北的区域;
  • 之前只能手动调整setView的纬度坐标来勉强实现居中,但这只是临时 workaround,希望从视口根源解决问题;
  • 发现调整浏览器窗口大小时,地图会自动居中,希望重置按钮也能实现该效果。

解决办法

核心原因是地图容器尺寸变化后,Leaflet未自动重新计算视口参数。通过模拟浏览器窗口resize事件,可以触发Leaflet重新校准地图视口,彻底解决偏移问题。

在切换地图/表格状态的observeEvent末尾添加以下代码:

shinyjs::runjs("window.dispatchEvent(new Event('resize'));")

添加后无需再手动调整setView的坐标,无论怎么切换表格显示状态,点击重置按钮地图都能正确居中。

修正后的完整代码

library(shiny)
library(shinyjs)
library(DT)
library(leaflet)
library(leaflet.extras)


ui <- fluidPage(
  useShinyjs(),
  tags$head(
    tags$style(HTML('
      /* Adjust the main panel style */
      .mainPanel {
        height: calc(140vh - 75px);
        display: flex;
        flex-direction: column;
        align-items: flex-start;
      }

      /* Adjust the map height */
      #map {
        flex-grow: 1;
        height: 70vh !important; 
      }

      /* Adjust the reset button style */
      .reset-button {
        position: absolute;
        top: 1em;
        right: 1em;
      }
      
      .mainPanel {
        position: relative;
        overflow: hidden;
      }
      
      .output-container {
        width: 100%;
        height: 100px; 
        transition: height 0.3s ease; 
      }
      
      .collapsed {
        height: 0 !important; /* Set height to 0 when collapsed */
        overflow: hidden; /* Hide content when collapsed */
      }
      
      .expanded {
        height: 200px !important; /* Calculate available height when expanded */
      }
    '))
  ),
  
  sidebarLayout(
    sidebarPanel(
    ),
    mainPanel(
      div(class = "mainPanel",
        leafletOutput("map"),
        div(
          class = "button-container",
          actionButton('toggleSizeButton', 'Expand Map')
        ),
        div(
          id = "outputContainer",
          style = "width: 100%; height: calc(100vh - 200px); overflow-y: auto;",
          DT::dataTableOutput("table")
        )
      )
    )
  )
)  

server <- function(input, output, session) {
 
  tableState <- reactiveVal(FALSE)
  
  observeEvent(tableState(), {
    toggleLabel <- ifelse(tableState(), "Show Table", "Expand Map")
    updateActionButton(session, "toggleSizeButton", label = toggleLabel)
  })
  
  observeEvent(input$toggleSizeButton, {
    tableState(!tableState()) 
    shinyjs::toggleClass(selector = "#outputContainer", class = "collapsed")
    
    toggleState <- input$toggleSizeButton %% 2 == 0
    
    if (!toggleState) {
      shinyjs::show("outputContainer")
      leafletProxy("map") %>%
        setView(lat = 36.1627, lng = -86.7816, zoom = 12)
      
    } else {
      leafletProxy("map") %>%
        setView(lat = 36.1627, lng = -86.7816, zoom = 11) # 无需再手动调整坐标
    }
    # 触发resize事件,让Leaflet重新计算视口
    shinyjs::runjs("window.dispatchEvent(new Event('resize'));")
  })
    
    output$map <- renderLeaflet({
      
      leaflet() %>% 
        addProviderTiles("CartoDB.DarkMatter") %>%
        setView(lat = 36.1627, lng = -86.7816, zoom = 11) %>%  
        addResetMapButton() # 现在在任何状态下点击都能正确居中
    })
    
    output$table <- DT::renderDataTable({
      mtcars
    })
}

shinyApp(ui = ui, server = server)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 15:27:45