如何在R中实现Leaflet Choropleth与Plotly的客户端双向联动
Leaflet分级着色地图与Plotly柱状图的客户端双向联动方案(非Shiny)
问题背景
需要实现Leaflet分级着色地图和Plotly柱状图的客户端双向联动:hover/点击柱子时地图对应区域高亮,反之亦然,但遇到SpatialPolygonsDataFrame与普通数据框无法通过crosstalk共享数据的问题。
解决方案
核心思路是将空间数据转为GeoJSON格式,用crosstalk::SharedData统一包装数据源,让Leaflet和Plotly共享同一标识键实现联动。以下是完整可运行代码:
library(leaflet) library(plotly) library(geojsonio) library(crosstalk) library(htmltools) # 加载空间数据并转换为GeoJSON格式 states_sp <- geojson_read("https://rstudio.github.io/leaflet/json/us-states.geojson", what = "sp") states_geojson <- geojson_json(states_sp, pretty = FALSE) # 创建共享数据,以州名作为唯一匹配键 shared_states <- SharedData$new( states_geojson, key = ~name, group = "state-data" ) # 定义颜色分箱和悬浮标签 bins <- c(0, 10, 20, 50, 100, 200, 500, 1000, Inf) pal <- colorBin("YlOrRd", domain = states_sp$density, bins = bins) labels <- sprintf( "<strong>%s</strong><br/>%g people / mi<sup>2</sup>", states_sp$name, states_sp$density ) %>% lapply(HTML) # 构建联动版Leaflet地图 mp <- leaflet() %>% setView(-96, 37.8, 4) %>% addGeoJSON( shared_states, fillColor = ~pal(density), weight = 2, opacity = 1, color = "white", dashArray = "3", fillOpacity = 0.7, highlightOptions = highlightOptions( weight = 5, color = "#666", dashArray = "", fillOpacity = 0.7, bringToFront = TRUE ), label = labels, labelOptions = labelOptions( style = list("font-weight" = "normal", padding = "3px 8px"), textsize = "15px", direction = "auto" ) ) %>% addLegend(pal = pal, values = states_sp$density, opacity = 0.7, title = NULL, position = "bottomright") # 构建联动版Plotly柱状图 fig <- plot_ly( shared_states$data(), x = ~name, y = ~density, type = 'bar', key = ~name ) %>% highlight( on = "plotly_hover", off = "plotly_unhover", color = "#1f77b4", opacityDim = 0.3 ) %>% layout(xaxis = list(title = "州名", tickangle = 45)) # 组合组件并启用联动 bscols(mp, fig)
关键细节说明
- 数据统一:用
SharedData包装GeoJSON数据,指定key = ~name作为跨组件的匹配标识,解决了空间数据和普通数据框的类型冲突 - Leaflet适配:改用
addGeoJSON加载共享数据,替代原addPolygons,确保能响应crosstalk的交互事件 - 双向联动逻辑:
- Hover柱状图柱子时,地图对应州多边形自动高亮
- Hover地图多边形时,柱状图对应柱子自动高亮
- 若要改为点击联动,只需将Plotly的
highlight(on = "plotly_hover")改为on = "plotly_click"即可
内容的提问来源于stack exchange,提问作者Will
相关产品推荐
相关产品推荐

