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)
}