前端怎么完成从 SHP文件 到 GeoJSON 的转化?

GeoJSON & SHP文件 是什么

什么是 GeoJSON

GeoJSON是一种基于JSON(JavaScript Object Notation)的格式,用于表示地理空间数据。

一般来说,渲染地图时,我们直接拿到 GeoJSON ,按照其格式解析成地图需要的数据即可。

但是,现在有一种情况是,不提供 GeoJSON ,而是提供 ArcGIS 编辑的 SHP文件 ,来渲染地图。

什么又是 SHP 文件

SHP文件(Shapefile)是一种常用的地理信息系统(GIS)矢量数据格式,它广泛应用于各种GIS软件中。SHP并不是指的单个文件,而是由多个文件组成的一个文件集,这些文件共同描述了地理数据及其属性。

SHP文件包括:shp、prj、shx、cpg 等

这中间其实就是多了一个 shp文件------GeoJSON 的转化。

怎么转化

完成这个转化,有很多方法:

  • 方法一:专门的转化工具软件
  • 方法二:python 和 java 等对应的后端库
  • 方法三:js 前端库

一般来说,在程序开发中,方法一和软件系统结合性较低,一般不用。我们通常使用的方法是由后端来转化,速度相对较快。当然,前端也有转化的方法,而这正是本文的主题:使用shpjs进行转化。

先贴下仓库地址:shp2geojson: 本项目使用shpjs将SHP文件转化为GeoJSON (gitee.com)

上传 SHP文件集压缩包 即可解析为 GeoJSON ,如果对你有帮助,欢迎 start

下面来讲讲几个关键步骤的实现

实现方法

首先安装需要的npm包

cmd 复制代码
pnpm i jszip shpjs -d

这里jszip是为了将zip文件解析为二进制数据,直接使用zip文件的File对象是会报错的

转化函数

js 复制代码
import JSZip from 'jszip'
import shp from 'shpjs'

/**
 * 将 shp 转化为 json
 * @param zip
 * @returns {Promise<*>}
 */
export const parseZip = async(zip) => {
  const jsZip = new JSZip()
  const zipData = await jsZip.loadAsync(zip)
  // 将zip文件转化为二进制流
  const data = await zipData.generateAsync({ type: 'arraybuffer' })
  return await shp(data)
}

调用时,将 File 对象传入即可

js 复制代码
const handleUpload = (file) => {
  // 判断文件是否为合规
  if(!fileValid(file)) {
    return false
  }
  // 转化
  parseZip(file).then(res => {
    jsonData.value = res
  })
  // 阻止 upload 组件默认上传事件
  return false
}

如果你的 SHP文件 当中需要解析中文,关注 cpg文件 即可

若 cpg文件 异常或者缺少 cpg文件 ,导致中文乱码,可以先做一个预处理

添加以下函数

js 复制代码
/**
 * 该函数可以重置 cpg文件编码格式
 * @param zip
 * @param format
 * @returns {Promise<*>}
 */
export const initCpg = async(zip, format) => {
  const jsZip = new JSZip()

  const zipData = await jsZip.loadAsync(zip)
  const fileNames = Object.keys(zipData.files)

  let hasCpg = false;
  // 遍历文件列表,删除后缀为 .cpg 的文件
  fileNames.forEach((fileName) => {
    // 检查文件扩展名是否为 .cpg
    if (fileName.endsWith('.cpg')) {
      hasCpg = true;
      // 删除原有的文件,插件新的编码格式的文件
      delete zipData.files[fileName]
      zipData.file(fileName, format)
    }
  })
  
  if(!hasCpg) {
    zipData.file(fileName, format)
  }

  return await zipData.generateAsync({ type: 'arraybuffer' })
}

更改转化函数

js 复制代码
/**
 * 将 shp 转化为 json
 * @param zip
 * @returns {Promise<*>}
 */
export const parseZip = async(zip) => {
  // 如果遇到实际编码格式与 cpg文件不符合的情况,可以使用下面注释的这段代码
  // format 取实际编码格式:'gb2312'或者'utf-8',或者其他编码类型
  const format = 'gb2312'
  const data = await initCpg(zip, format)
  return await shp(data)
}

资源

  1. shpjs - shpjs - npm (npmjs.com)
  2. jszip - jszip - npm (npmjs.com)
  3. 前端往读取到的压缩文件里添加文件,针对了shapefile(shp)压缩文件里没有.cfg导致中文乱码的情况 - doraemon22333 - 博客园 (cnblogs.com)
相关推荐
程序员大阳8 小时前
HTML+CSS+JS对话式实战(5)-活动管理页之查看报名名单的实现
javascript·css·html·查看报名名单
xbzb10 小时前
镜像到底存在哪:/var/lib/docker 的四级映射与 daemon.json 配置
docker·容器·json·镜像·daemon.json·四级
新*10 小时前
从一段 WebSocket 代码聊开:bytes 不是 zlib、binaryType 决定一切,15MB 大消息的零拷贝优化
javascript·python·websocket·性能优化·blob·zlib·arraybuffer
OpsEye11 小时前
别再挨个充会员了:多模型编码,最麻烦的从来不是选模型
javascript·ai编程
学以智用13 小时前
jsencrypt.js 完整详解
javascript
总要学点什么15 小时前
第96篇:三维数据加载-城市建筑白模样式+着色器——让色带按体量上色,最白的那档却涂不上去
前端·gis·webgl·cesium·着色器·空间分析·白模
Hilaku15 小时前
你们公司有 35 岁以上的前端吗?
前端·javascript·程序员
鸿蒙开发16 小时前
小程序存档写到一半怎么办?双槽保存与损坏恢复实战
前端·javascript·react.js
坤坤子吖16 小时前
Linux网络编程:自定义应用层协议与 JSON 序列化
linux·服务器·网络·c++·笔记·json
知忆_IS17 小时前
TerriaMap 开发实战04:MVT数据自定义符号化 - terriajs源码修改
javascript·webgis·terriamap·terriajs