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

R Shiny中mapedit editMod加载Shapefile无法在地图显示的求助

问题描述

在R Shiny应用中使用editMod()实现手动绘制多边形或加载Shapefile功能时,面积计算功能正常,但加载的Shapefile无法在editMod绑定的Leaflet地图上显示,仅能参与后续面积计算。

解决方法

问题根源是加载的Shapefile未被添加到editMod对应的Leaflet地图实例中。需要通过以下步骤修复:

  • 利用editMod返回的地图引用,在Shapefile加载完成后动态添加到地图上
  • 使用leafem::addFeatures实现矢量要素的添加,并通过Shiny的session对象触发地图更新
  • 优化文件保存逻辑,避免同名文件覆盖(可选)
修改后的完整代码
### 加载依赖包
library(dplyr)
library(plyr)
library(shiny)
library(leaflet)
library(mapedit)
library(sf)
library(leaflet.esri)
library(leafem)
library(DT)
library(shinycssloaders)
library(htmlwidgets)

#################
### 创建UI ###
#################
ui <- shinyUI(
  fluidPage(
    sidebarLayout(
      # 地图面板
      mainPanel(
        editModUI("map", height=600),
        fileInput("filemap", "上传Shapefile", accept=c('.shp','.dbf','.sbn','.sbx','.shx',".prj"), multiple=TRUE)
      ),
      # 结果面板
      sidebarPanel(
        actionButton("calc_button", "计算面积", icon = icon("arrow-right")),
        conditionalPanel(condition = "input.calc_button >= 1",
                         withSpinner(DT::DTOutput('TableIndex'))
        )
      )
    )
  )
)

#####################
### 创建server ###
#####################

server <- function(input, output, session) {
  
  ### 响应式变量定义
  shp_impact <- reactiveVal(data.frame())
  LoadedShape <- reactiveVal(data.frame())
  TableIndex <- reactiveVal()
  
  ### 初始化编辑地图
  # 保存editMod返回的地图引用,用于后续更新
  map_edit_result <- callModule(
    editMod,
    leafmap = leaflet() %>%
      addTiles(group="OpenStreetMap") %>%
      addDrawToolbar(
        polylineOptions = FALSE,
        circleOptions = FALSE,
        rectangleOptions = FALSE,
        markerOptions = FALSE,
        circleMarkerOptions = FALSE,
        editOptions=editToolbarOptions(edit=TRUE, remove=TRUE)
      ),
    id = "map",
    record = FALSE,
    sf = TRUE
  )
  
  ### 加载并显示Shapefile
  observeEvent(input$filemap, {
    
    # 创建临时目录保存上传的文件,避免同名覆盖
    temp_dir <- tempdir()
    for(i in 1:nrow(input$filemap)){
      file.copy(input$filemap$datapath[i], file.path(temp_dir, input$filemap$name[i]))
    }
    
    # 检查Shapefile完整性
    Names_comb <- paste(input$filemap$name, collapse="_")
    if(!all(c(".dbf", ".shp", ".prj", ".shx") %in% tools::file_ext(input$filemap$name))){
      showNotification(ui=HTML("<b>无效的Shapefile:必须包含.shp, .shx, .prj, .dbf文件</b>"), type="error", duration=8)
      return(data.frame())
    }
    
    # 读取并转换坐标系
    ShapeName <- file.path(temp_dir, input$filemap$name[tools::file_ext(input$filemap$name)=="shp"])
    Shape <- st_read(ShapeName) %>% st_transform(4326)
    
    LoadedShape(Shape)
    
    # 将加载的Shapefile添加到editMod的地图上
    map_edit_result$map_proxy %>%
      addFeatures(Shape, color = "#ff0000", weight = 2, fillOpacity = 0.3) %>%
      updateMapedit(session, "map")
  })
  
  ### 计算面积
  observeEvent(input$calc_button, {
    
    # 合并绘制的要素和加载的Shapefile
    drawn_data <- map_edit_result$finished()
    loaded_data <- LoadedShape()
    
    if(nrow(drawn_data) > 0 && nrow(loaded_data) == 0){
      shp_impact(drawn_data)
      print("数据来源:仅手动绘制")
    } else if(nrow(drawn_data) == 0 && nrow(loaded_data) > 0){
      shp_impact(loaded_data)
      print("数据来源:仅上传的Shapefile")
    } else if(nrow(drawn_data) > 0 && nrow(loaded_data) > 0){
      shp_impact(rbind(drawn_data[, "geometry"], loaded_data[, "geometry"]))
      print("数据来源:手动绘制+上传Shapefile")
    }
    
    # 生成结果表格
    if(nrow(shp_impact()) > 0){
      TableIndex(data.frame(Area = st_area(shp_impact())))
    }
  })
  
  ### 输出结果表格
  output$TableIndex <- DT::renderDT({
    req(TableIndex())
    TableIndex()
  })
}

###########
### 运行应用 ###
###########

shinyApp(ui = ui, server = server)
关键修改点说明
  1. 保存地图引用:将editMod的返回值赋值给map_edit_result,通过map_edit_result$map_proxy获取地图代理对象,用于后续动态更新。
  2. 动态添加要素:在Shapefile加载完成后,调用addFeatures将其添加到地图,再通过updateMapedit触发地图刷新。
  3. 临时目录优化:使用tempdir()创建临时目录保存上传文件,避免同名文件覆盖导致读取错误。
  4. 文件检查优化:用tools::file_ext替代字符串截取,更可靠地检查文件扩展名。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 16:11:21