前端怎么完成从 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 的转化。

怎么转化

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

  • 方法一:专门的转化工具软件
  • 方法二:pythonjava 等对应的后端库
  • 方法三: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)
相关推荐
Anson Jiang22 分钟前
浏览器标签页管理:使用chrome.tabs API实现新建、切换、抓取内容——Chrome插件开发从入门到精通系列教程06
开发语言·前端·javascript·chrome·ecmascript·chrome devtools·chrome插件
掘金安东尼25 分钟前
黑客劫持:周下载量超20+亿的NPM包被攻击
前端·javascript·面试
剑亦未配妥1 小时前
移动端触摸事件与鼠标事件的触发机制详解
前端·javascript
前端君9 小时前
实现最大异步并发执行队列
javascript
知识分享小能手10 小时前
React学习教程,从入门到精通,React 组件核心语法知识点详解(类组件体系)(19)
前端·javascript·vue.js·学习·react.js·react·anti-design-vue
蚂蚁RichLab前端团队11 小时前
🚀🚀🚀 RichLab - 花呗前端团队招贤纳士 - 【转岗/内推/社招】
前端·javascript·人工智能
萌萌哒草头将军12 小时前
Oxc 和 Rolldown Q4 更新计划速览!🚀🚀🚀
javascript·vue.js·vite
Qlittleboy12 小时前
uniapp如何使用本身的字体图标
javascript·vue.js·uni-app
林_深时见鹿12 小时前
Vue + ElementPlus 自定义指令控制输入框只可以输入数字
前端·javascript·vue.js
GDAL12 小时前
Knockout.js 任务调度模块详解
javascript·knockout