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

实现DT表格与Leaflet地图的双向交互及点样式控制

实现双向交互与地图点样式控制

核心修改思路

  • 给每个地图标记分配唯一layerId,用于精准关联表格行
  • 监听表格选中事件,动态调整地图标记的样式
  • 监听地图标记点击事件,同步选中表格对应行
  • 通过leafletProxy实现地图局部更新,避免重绘整个地图影响性能

修改后的完整代码

library(dplyr)
library(shiny)
library(leaflet)
library(DT)
library(crosstalk)

set.seed(123) # 固定随机数,方便复现结果
data <- data.frame(
  Lon = rnorm(10, -85, 2), 
  Lat = rnorm(10, 40, 1), 
  Group = rep(c("a", "b"), 5),
  row.names = paste0("point_", 1:10) # 自定义唯一标识,也可直接用默认行号
)

ui <- fluidPage(
  fluidRow(
    column(6, leafletOutput("Map")),
    column(6, DT::dataTableOutput("Table", width = "100%"))
  )
)

server <- function(input, output, session) {
  # 创建共享数据,用行名作为唯一关联键
  shared <- SharedData$new(data, key = ~row.names(data))
  
  # 初始化地图
  output$Map <- renderLeaflet({
    leaflet(data) %>%
      addProviderTiles("Esri.WorldImagery", layerId = "basetile",
                       options = providerTileOptions(opacity = 0.75)) %>%
      addCircleMarkers(
        lng = ~Lon, lat = ~Lat,
        layerId = ~row.names(data), # 绑定唯一ID,用于后续定位
        color = "blue", radius = 6,
        opacity = 1, fillOpacity = 0.8,
        stroke = TRUE, weight = 2
      )
  })
  
  # 渲染DT表格
  output$Table <- DT::renderDataTable({
    shared
  }, 
  selection = "single", 
  options = list(autoWidth = TRUE, paging = FALSE), 
  server = FALSE)
  
  # 监听表格选中事件:高亮对应地图点
  observeEvent(input$Table_rows_selected, {
    selected_row <- input$Table_rows_selected
    if (!is.null(selected_row)) {
      # 获取选中点的唯一ID
      selected_id <- row.names(data)[selected_row]
      
      # 更新地图样式:选中点高亮,其他点降低透明度
      leafletProxy("Map", session) %>%
        # 先重置所有点为未选中样式
        setCircleMarkerStyle(
          layerId = row.names(data),
          color = "blue", radius = 6,
          opacity = 0.3, fillOpacity = 0.2,
          stroke = TRUE, weight = 2
        ) %>%
        # 设置选中点的高亮样式
        setCircleMarkerStyle(
          layerId = selected_id,
          color = "red", radius = 8,
          opacity = 1, fillOpacity = 0.9,
          stroke = TRUE, weight = 3
        )
    } else {
      # 无选中行时,重置所有点为初始样式
      leafletProxy("Map", session) %>%
        setCircleMarkerStyle(
          layerId = row.names(data),
          color = "blue", radius = 6,
          opacity = 1, fillOpacity = 0.8,
          stroke = TRUE, weight = 2
        )
    }
  })
  
  # 监听地图点点击事件:高亮对应表格行
  observeEvent(input$Map_marker_click, {
    click <- input$Map_marker_click
    if (!is.null(click)) {
      # 将点的唯一ID转换为表格行号
      selected_row <- which(row.names(data) == click$id)
      # 更新表格选中状态
      updateDT(session, "Table", selected = selected_row)
    }
  })
}

shinyApp(ui, server)

关键功能说明

  1. 双向交互实现

    • 表格到地图:通过observeEvent(input$Table_rows_selected)捕获选中行,利用leafletProxy精准修改对应标记的样式
    • 地图到表格:通过observeEvent(input$Map_marker_click)捕获点击的标记ID,转换为表格行号后用updateDT同步选中状态
  2. 样式控制

    • 未选中点:设置低透明度(opacity=0.3、fillOpacity=0.2),保留蓝色默认配色
    • 选中点:增大标记半径、改用红色、提高透明度,通过视觉差异突出选中状态
    • 无选中状态时,自动重置所有点为初始样式
  3. 性能优化

    • 使用leafletProxy局部更新地图,避免每次交互重绘整个地图,提升响应速度
    • 用唯一layerId定位单个标记,无需清除所有标记再重新添加,减少不必要的计算

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 08:42:22