在Leaflet中能否连续执行两次flyTo方法?相关报错如何解决?
Leaflet地图平滑平移功能报错排查
功能需求
创建Leaflet地图,初始默认位置缩放等级为4渲染,用户点击go按钮后,从下拉选择框选中的起点位置平滑平移到选中的终点位置。
实现效果参考

问题代码
library(sf) library(tigris) library(shiny) library(shinydashboard) library(tidyverse) library(leaflet) # 数据加载与处理 USA <- st_read(dsn = 'data/cb_2018_us_county_5m.shp') counties_sf <- st_as_sf(USA) counties_reproject_sf <- st_transform(counties_sf, 4326) %>% filter(COUNTYFP < 60010) emp_rate <- read_csv('data/synthetic_emp_rate_pred.csv') emp_rate$countyfips <- sprintf("%05d", emp_rate$countyfips) states_sf_coef <- geo_join(counties_reproject_sf, emp_rate, "GEOID", "countyfips", how='inner') ui <- fluidPage( dashboardPage( dashboardHeader(title="Employee Rate Data"), dashboardSidebar( sidebarMenu( menuItem( "Maps", tabName = "maps", icon=icon("globe") ) ) ), dashboardBody( tabItems( tabItem( tabName = "maps", tags$style(type="text/css","#all_airports {height:calc(100vh - 80px) !important;}"), fluidRow(column(4), column(8, selectInput(inputId = "FromCounty", label="from", choices=c(unique(emp_rate$countyname)), selected = 'Travis County, Texas' ), selectInput(inputId = "ToCounty", label = "to", choices=c(unique(emp_rate$countyname)) ))), actionButton("zoomer","go"), leafletOutput("map") ) ) ) ) ) server <- function(input, output, session) { # 地图渲染 output$map <- renderLeaflet({ mypal <- colorNumeric(palette="viridis", domain=states_sf_coef$rand_pred, na.color="transparent") leaflet() %>% addProviderTiles("OpenStreetMap.Mapnik") %>% setView(lat = 38.2393, lng = -96.3795, zoom = 4) %>% addPolygons( data = states_sf_coef, fillColor = ~mypal(rand_pred), stroke = FALSE, smoothFactor = 0.2, fillOpacity = 0.3, popup = paste( "Region: ", states_sf_coef$countyname, "<br>", "Social Index: ", states_sf_coef$rand_pred, "<br>" ) ) }) map_proxy <- leafletProxy("map") observeEvent(input$zoomer, { # 起点处理 fromCountyInput <- reactive({ states_sf_coef %>% dplyr::filter(countyname == input$FromCounty) }) fromData <- fromCountyInput() fromCoords <- st_coordinates(st_centroid(fromData$geometry)) # 终点处理 toCountyInput <- reactive({ states_sf_coef %>% dplyr::filter(countyname == input$ToCounty) }) toData <- toCountyInput() toCoords <- st_coordinates(st_centroid(toData$geometry)) map_proxy %>% flyTo(lng = fromCoords[1], lat = fromCoords[2], zoom = 10) flyTo(lng = toCoords[1], lat = toCoords[2], zoom = 10) }) } # 启动应用 shinyApp(ui = ui, server = server)
报错信息
Warning: Error in dispatch: argument "map" is missing, with no default
问题成因
- 核心错误是
observeEvent中调用flyTo的链式语法错误:第一次flyTo调用结束后没有补充管道符%>%,导致第二个flyTo没有接收到map_proxy传入的地图对象作为必填参数,触发参数缺失报错。 - 隐藏问题:连续调用两次
flyTo会导致动画冲突,默认只会生效最后一次飞行,无法实现先定位起点再平移到终点的效果。 - 冗余代码:在
observeEvent内部嵌套定义reactive表达式属于不必要的写法,会增加额外的响应式开销。
解决方法
直接替换原有observeEvent代码段即可:
observeEvent(input$zoomer, { # 直接过滤获取起点数据 fromData <- states_sf_coef %>% dplyr::filter(countyname == input$FromCounty) fromCoords <- st_coordinates(st_centroid(fromData$geometry)) # 直接过滤获取终点数据 toData <- states_sf_coef %>% dplyr::filter(countyname == input$ToCounty) toCoords <- st_coordinates(st_centroid(toData$geometry)) # 先飞到起点 map_proxy %>% flyTo(lng = fromCoords[1], lat = fromCoords[2], zoom = 10) # 延迟2秒后飞到终点,避免动画冲突,可根据需求调整延迟时长 invalidateLater(2000, session) map_proxy %>% flyTo(lng = toCoords[1], lat = toCoords[2], zoom = 10) })
如果不需要停留展示起点,直接从当前位置平滑飞到终点,直接保留一次flyTo调用即可:
observeEvent(input$zoomer, { toData <- states_sf_coef %>% dplyr::filter(countyname == input$ToCounty) toCoords <- st_coordinates(st_centroid(toData$geometry)) map_proxy %>% flyTo(lng = toCoords[1], lat = toCoords[2], zoom = 10) })
内容的提问来源于stack exchange,提问作者Erin
相关产品推荐
相关产品推荐

