Shiny中Tab切换后Leaflet地图显示异常问题求助
Shiny中Tab切换后Leaflet地图显示异常的解决方案
问题解决说明
经ghybs的评论提示,该问题已解决,解决方案如下:
最终解决方案
在实际代码中,由于存在多个可修改地图数据的UI输入(部分为全局UI元素,可在站点其他部分修改),且使用leafletProxy添加标记,最终方案是创建一个观察者:
- 先延迟100ms调用
invalidateSize(),让Leaflet重新计算地图尺寸 - 再至少延迟100ms后,通过
leafletProxy执行fitBounds(),将地图居中到数据范围
原问题描述
我用Shiny开发了一个带有page_navbar和多个菜单选项的应用,其中一个菜单是「密度图」,核心是包含addCircleMarkers的Leaflet地图。为了对比同一物种不同时间段的密度数据,我设置了一个tabset,两个Tab分别对应不同时间段的Leaflet地图。
首次进入「密度图」菜单时一切正常,但切换到其他主菜单选项后再返回「密度图」,点击之前处于隐藏状态的Tab时,Leaflet地图会出现显示异常:地图区域有灰色块,且未自动居中到标记位置。
最简复现代码
library(shiny) library(leaflet) library(bslib) ui <- tagList( page_navbar( id = "nav", title = "Leaflet Maps in Tabs", sidebar = sidebar( id = "global_sidebar", nav_panel("Placeholder") ), # Home tab nav_panel("Home", p("Welcome to the Home Page!") ), # Maps tab with tabset nav_panel("Maps", tabsetPanel( id = "map_tabs", tabPanel("Current", leafletOutput("current_map") ), tabPanel("Previous", leafletOutput("previous_map") ) ) ) ) ) server <- function(input, output, session) { output$current_map <- renderLeaflet({ current_markers <- data.frame( lat = c(37.7749, 34.0522), lng = c(-122.4194, -118.2437) ) leaflet() %>% addTiles() %>% addMarkers( data = current_markers, lng = ~lng, lat = ~lat, popup = ~paste("Location:", lat, lng) ) }) output$previous_map <- renderLeaflet({ previous_markers <- data.frame( lat = c(40.7128, 42.3601), lng = c(-74.0060, -71.0589) ) leaflet() %>% addTiles() %>% addMarkers( data = previous_markers, lng = ~lng, lat = ~lat, popup = ~paste("Location:", lat, lng) ) }) } shinyApp(ui = ui, server = server)
复现步骤
含侧边栏场景
- 点击「Maps」,确认两个Tab下的地图均正常显示
- 隐藏全局侧边栏
- 切换到「Home」菜单
- 重新显示全局侧边栏
- 切换回「Maps」菜单
- 点击之前切换时处于隐藏状态的另一个地图Tab
此时地图会出现灰色区域,虽可手动拖动回到标记中心,但超出边界后灰色区域会覆盖地图,导致无法正常使用。
无需侧边栏场景
- 点击「Maps」,确认两个Tab下的地图均正常显示
- 按F12打开浏览器开发者工具
- 切换到「Home」菜单
- 按F12关闭开发者工具
- 切换回「Maps」菜单
- 点击之前切换时处于隐藏状态的另一个地图Tab
实际代码细节与异常表现
实际代码中还有以下差异:
- 为地图高度设置了CSS样式
- 使用
leafletProxy更新地图内容,调用fitBounds()自动居中 - 除
addMarkers外,还使用了addCircleMarkers和addLegend
出现异常时,地图的图例和普通标记仍存在,但circlemarkers会消失,同时伴随灰色区域和未居中的问题。
我并非专业开发者,这是一个志愿项目。试过多种代码改写,上述是能复现问题的最简版本,也曾尝试监听Tab点击事件,调用update_density_map()函数(通过leafletProxy更新地图),但未能解决问题。想请教是否应该放弃Tab式的Leaflet地图布局,或者有其他可行的解决方法。
测试环境
- 操作系统:Windows 11 23H2
- 浏览器:Chrome 130.0.6723.70(64位)、Edge 130.0.2849.52(64位)
- R版本:4.4.1
- 包版本:leaflet 2.2.2,shiny 1.9.1
内容的提问来源于stack exchange,提问作者Blair
相关产品推荐
相关产品推荐

