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

在R中实现可点击缩放的Leaflet地图:点击省份显示对应市镇

实现西班牙省份点击缩放+显示对应市镇的交互式Leaflet地图

针对你的需求,下面分两种场景给出解决方案:纯静态Leaflet前端交互,以及能存储用户选择的Shiny交互式应用,同时修正你原代码里的几个基础错误:

  • 原代码中st_transform(provincias, crs = 4326)参数错误,应使用管道对象指代符或直接省略参数对象
  • 筛选马德里区域时误用了自治区字段ine.ccaa.name,精准筛选省份应使用ine.prov.code(唯一编码)或ine.prov.name

步骤1:基础数据预处理

先统一获取并转换西班牙省份、市镇数据到Leaflet支持的WGS84坐标系(EPSG:4326):

library(mapSpain)
library(tidyverse)
library(leaflet)
library(htmlwidgets) # 用于纯Leaflet的JS交互逻辑

# 省份数据
provincias <- esp_get_prov() %>%
  st_transform(crs = 4326)

# 所有市镇数据
municipios <- esp_get_munic() %>%
  st_transform(crs = 4326)

场景1:纯静态Leaflet前端交互(无需Shiny)

通过自定义JavaScript实现点击省份时自动缩放、加载对应市镇图层:

leaflet(provincias) %>%
  addProviderTiles(providers$Stamen.Toner) %>%
  # 添加省份图层,绑定唯一编码作为图层ID
  addPolygons(
    layerId = ~ine.prov.code,
    fillOpacity = 0.5,
    color = "#000000",
    weight = 1,
    popup = ~ine.prov.name
  ) %>%
  # 注入JS逻辑处理点击事件
  onRender(JS("function(el, x) {
    var map = this;
    // 将R端的市镇数据转为JS可识别的JSON格式
    var allMunis = ", htmlwidgets::toJSON(municipios), ";
    
    // 监听省份图层点击
    map.on('click', function(e) {
      var target = e.target;
      // 仅处理省份图层的点击
      if (target.options.layerId) {
        var provCode = target.options.layerId;
        
        // 缩放至点击的省份区域
        map.fitBounds(target.getBounds());
        
        // 清除已加载的旧市镇图层
        if (map.hasLayer('muniLayer')) {
          map.removeLayer('muniLayer');
        }
        
        // 筛选对应省份的市镇数据
        var filteredMunis = allMunis.features.filter(function(muni) {
          return muni.properties.ine.prov.code === provCode;
        });
        
        // 添加市镇图层
        var muniLayer = L.geoJSON(filteredMunis, {
          fillOpacity: 0.3,
          color: '#ff0000',
          weight: 0.5,
          popup: function(feature) {
            return feature.properties.ine.muni.name;
          }
        }).addTo(map);
        
        // 给市镇图层标记ID,方便后续清除
        muniLayer.options.layerId = 'muniLayer';
      }
    });
  }"))

场景2:Shiny交互式应用(存储用户选择的省份)

如果需要持久存储用户选择的省份并做后续分析,Shiny是更便捷的方案:

library(shiny)

ui <- fluidPage(
  leafletOutput("provMap"),
  # 展示用户选中的省份
  div(style = "margin:10px;", 
      h4("你选择的省份:"),
      verbatimTextOutput("selectedProv"))
)

server <- function(input, output, session) {
  # 预加载数据
  provincias <- esp_get_prov() %>% st_transform(crs = 4326)
  municipios <- esp_get_munic() %>% st_transform(crs = 4326)
  
  # 初始化省份地图
  output$provMap <- renderLeaflet({
    leaflet(provincias) %>%
      addProviderTiles(providers$Stamen.Toner) %>%
      addPolygons(
        layerId = ~ine.prov.code,
        fillOpacity = 0.5,
        color = "#000000",
        weight = 1,
        popup = ~ine.prov.name,
        highlight = highlightOptions(weight = 2, color = "#666")
      )
  })
  
  # 监听地图点击事件,处理省份选择
  observeEvent(input$provMap_shape_click, {
    click_info <- input$provMap_shape_click
    selected_code <- click_info$id
    
    # 获取并存储选中省份的名称
    selected_name <- provincias %>%
      filter(ine.prov.code == selected_code) %>%
      pull(ine.prov.name) %>%
      unique()
    
    # 输出选中的省份信息
    output$selectedProv <- renderPrint({
      cat(selected_name)
    })
    
    # 筛选对应省份的市镇
    filtered_munis <- municipios %>%
      filter(ine.prov.code == selected_code)
    
    # 更新地图:缩放至选中区域+加载市镇图层
    leafletProxy("provMap") %>%
      fitBounds(
        lng1 = click_info$lng - 0.6, lat1 = click_info$lat - 0.6,
        lng2 = click_info$lng + 0.6, lat2 = click_info$lat + 0.6
      ) %>%
      clearGroup("municipios") %>%
      addPolygons(
        data = filtered_munis,
        group = "municipios",
        fillOpacity = 0.3,
        color = "#ff0000",
        weight = 0.5,
        popup = ~ine.muni.name
      )
  })
}

shinyApp(ui, server)

关键注意事项

  • 精准筛选:优先使用ine.prov.code(省份唯一编码)筛选市镇,比名称更可靠,避免重名问题
  • 图层管理:添加市镇图层时务必标记分组或ID,避免重复叠加旧图层
  • 场景选择:纯Leaflet方案适合静态网页展示,Shiny方案适合需要用户交互数据存储、后续分析的场景

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 23:27:45