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

基于R、Shiny与mapboxer迁移Leaflet至Mapbox的功能适配问题

Shiny迁移至mapboxer的三大功能适配解决方案

以下是针对你提出的三个核心需求的完整实现代码及说明,解决填充图层动态选择、区域视图适配、事件捕获的问题:

完整可运行代码

library(shiny)
library(mapboxer)
library(sf)
library(dplyr)

# 模拟墨尔本空间与属性数据(替换为你的实际数据)
MELBOURNE_MAP <- spData::melbourne |> 
  select(SA2_NAME, geometry)
MELBOURNE_DATA <- spData::melbourne |> 
  select(SA2_NAME, Median_income, Population)
# 合并空间与属性数据(确保主键匹配)
merged_data <- MELBOURNE_MAP |> 
  left_join(MELBOURNE_DATA, by = "SA2_NAME")

# UI 部分
ui <- fluidPage(
  tabsetPanel(
    tabPanel("Leaflet (原版本)", leafletOutput("leaflet_map")),
    tabPanel("Mapbox (迁移版本)", 
             sidebarLayout(
               sidebarPanel(
                 selectInput("fill_col", "选择填充列", 
                             choices = c("Median_income", "Population")),
                 selectInput("area_select", "选择区域适配范围", 
                             choices = c("全部区域", unique(MELBOURNE_MAP$SA2_NAME)))
               ),
               mainPanel(
                 mapboxerOutput("mapbox_map"),
                 h4("点击区域信息"),
                 verbatimTextOutput("click_info"),
                 h4("悬停区域信息"),
                 verbatimTextOutput("hover_info")
               )
             )
    )
  )
)

# Server 部分
server <- function(input, output, session) {
  # Leaflet 原版本(保持原有逻辑)
  output$leaflet_map <- renderLeaflet({
    leaflet(MELBOURNE_MAP) |> 
      addTiles() |> 
      addPolygons(fillColor = ~colorQuantile("YlOrRd", Median_income)(Median_income),
                  fillOpacity = 0.7,
                  color = "#BDBDC3",
                  weight = 1,
                  popup = ~paste(SA2_NAME, "<br>收入中位数:", Median_income)) |> 
      fitBounds(144.5, -38.5, 145.5, -37.5)
  })
  
  # Mapbox 核心渲染逻辑
  output$mapbox_map <- renderMapboxer({
    # 初始化地图,需替换为你的Mapbox API密钥
    mapboxer(
      style = mapbox_style("light"),
      center = c(144.9631, -37.8136),
      zoom = 10,
      access_token = "你的Mapbox API密钥"
    ) |> 
      # 添加填充图层,使用合并后的数据源
      add_fill_layer(
        source = as_mapbox_source(merged_data, id = "merged_data"),
        paint = list(
          "fill-color" = list(
            property = input$fill_col,
            stops = color_stops(merged_data[[input$fill_col]], palette = "YlOrRd")
          ),
          "fill-opacity" = 0.7,
          "fill-outline-color" = "#BDBDC3"
        ),
        id = "fill_layer"
      ) |> 
      # 绑定点击事件
      add_click_event(source = "merged_data", layer = "fill_layer", id = "map_clicked") |> 
      # 绑定悬停事件,设置停留时长
      add_hover_event(source = "merged_data", layer = "fill_layer", id = "map_hover", duration = 100)
  })
  
  # 动态更新填充图层颜色(切换列时)
  observeEvent(input$fill_col, {
    mapboxer_proxy("mapbox_map") |> 
      set_paint_property(
        layer = "fill_layer",
        name = "fill-color",
        value = list(
          property = input$fill_col,
          stops = color_stops(merged_data[[input$fill_col]], palette = "YlOrRd")
        )
      ) |> 
      update_mapboxer()
  })
  
  # 选择区域后适配地图范围
  observeEvent(input$area_select, {
    # 获取选中区域的边界框
    bbox <- if (input$area_select == "全部区域") {
      st_bbox(merged_data)
    } else {
      merged_data |> 
        filter(SA2_NAME == input$area_select) |> 
        st_bbox()
    }
    # 更新地图视图
    mapboxer_proxy("mapbox_map") |> 
      fit_bounds(bbox[["xmin"]], bbox[["ymin"]], bbox[["xmax"]], bbox[["ymax"]]) |> 
      update_mapboxer()
  })
  
  # 输出点击事件信息
  output$click_info <- renderPrint({
    req(input$map_clicked)
    input$map_clicked$properties
  })
  
  # 输出悬停事件信息
  output$hover_info <- renderPrint({
    req(input$map_hover)
    input$map_hover$properties
  })
}

shinyApp(ui, server)

关键功能适配说明

1. 动态选择数据列添加填充图层

  • 必须将空间数据与属性数据合并为单个sf对象,保证属性与空间要素一一对应
  • 使用as_mapbox_source()将sf数据转为Mapbox兼容的数据源,注意指定唯一的id便于后续引用
  • 填充颜色通过动态表达式生成,color_stops()会根据选中列的数值范围自动生成颜色映射
  • 切换列时用mapboxer_proxy()局部更新图层属性,避免重绘整个地图提升性能

2. 选择区域后自动适配地图范围

  • 监听区域选择框的输入变化,根据选择生成对应的边界框(bbox)
  • 调用fit_bounds()方法传入边界框的四个坐标值,通过mapboxer_proxy()实时更新地图视图
  • 支持"全部区域"和单个区域两种适配模式,覆盖不同使用场景

3. 捕获点击与悬停事件

  • 通过add_click_event()和add_hover_event()绑定事件,需指定数据源ID和图层ID
  • 事件触发后,可通过input$[事件ID]获取包含区域属性的返回值,input$map_clicked$properties即为点击区域的所有属性数据
  • 悬停事件可通过duration参数设置提示信息的停留时间,优化交互体验

注意事项

  • 需提前设置Mapbox API密钥,可通过mapboxer::set_mapbox_access_token("你的密钥")全局配置,或在mapboxer()函数中传入access_token参数
  • 确保合并数据时使用唯一主键(如示例中的SA2_NAME),避免数据匹配错误
  • 依赖包需安装完整:install.packages(c("shiny", "mapboxer", "sf", "dplyr", "spData"))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 11:01:08