shp转geojson、kml转geojson

导入效果:

用到的npm库

pnpm add shpjs // 或者 npm i shpjs 5.0.2
pnpm add jszip //  或者 npm i jszip 版本3.10.1
pnpm add @tmcw/togeojson // 或者 npm i @tmcw/togeojson 版本 5.8.1

创建方法用来区分导入的文件

1. 这里只是做了一个文件的区分 其中的kmlToGeoJson 和 readShp 、dealZip 具体方法会写明

// 处理文件
export const dealFile = async (file: UploadFile) => {
    let geoJson = undefined
    if (!file?.raw) return
    try {
        if (file?.name?.includes('.kml')) geoJson = await kmlToGeoJson(file.raw)
        else if (file?.name?.includes('.shp') || file?.name?.includes('.zip')) geoJson = await readShp(file.raw)
        else if (file?.name?.includes('.zip')) geoJson = await dealZip(file.raw)
        else ElMessage.warning(`本系统暂只支持${fileType}文件`)
    } catch (err) {
    }
    return geoJson
}

kml转换geojson

import {kml} from "@tmcw/togeojson";
const kmlToGeoJson = (file: UploadRawFile) => {
    let reader = new FileReader()
    reader.readAsText(file)
    return new Promise((resolve, reject) => {
        reader.onload = (e) => {
            // @ts-ignore 读取文件内容
            const fileString = e.target.result
            let geoJson = kml(new DOMParser().parseFromString(fileString as string, "text/xml"))
            resolve(geoJson)
        }
        reader.onerror = () => {
            ElMessage.error('kml文件读取失败') // 这个是ui报错可以不管他
            reject(reader.error)
        }
    })
}

shp转geojson

其中的方法dealZip 主要是处理压缩包的 shp文件有好多个合在一起的 不能单独传,单独传会报错。把所有的文件打包成一个压缩包在进行上传就可以了。

这里注意shp 不能直接引入shpjs 只能向我这种引入 

import shp from 'shpjs/dist/shp.js'
import JsZip from 'jszip'

// shapefile插件 shp转geo
const shpToGeoJson = async (data: ArrayBuffer) => {
    try {
        return await shp(data)
    } catch (e) {
        ElMessage.error('shp文件读取失败')
    }
}

const readShp = (file: UploadRawFile) => {
    let fileReader = new FileReader();
    fileReader.readAsArrayBuffer(file);
    return new Promise((resolve, reject) => {
        fileReader.onload = async (e) => {
            let fileString = e.target?.result
            let geoJson = fileString && await shpToGeoJson(fileString)
            geoJson && resolve(geoJson)
            geoJson || reject()
        }
        fileReader.onerror = () => {
            ElMessage.error('shp文件读取失败')
            reject(fileReader.error)
        }
    })
}


// 处理压缩包
const dealZip = async (file: UploadRawFile) => {
    const newZip = new JsZip()
    const res = await newZip.loadAsync(file)
    const fileList = Object.keys(res.files)
    const pattern = new RegExp(/\S\.shp$/)
    let shpFile = fileList.find(i => pattern.test(i))
    try {
        // @ts-ignore
        let res = await newZip.file(shpFile).async('arraybuffer')
        return await shpToGeoJson(res)
    } catch (err) {
        ElMessage.error('shp文件读取失败')
    }
}

完整代码

//  把kml 文件解析为geoJson
import {kml} from "@tmcw/togeojson";
// @ts-ignore  解析shp 文件
import shp from 'shpjs/dist/shp.js'
import JsZip from 'jszip'
import {ElMessage} from "element-plus";
import type {UploadFile, UploadRawFile} from "element-plus/lib/components/upload/src/upload";

export const fileType = ['kml', 'shp', 'zip']

// 把kml 文件转换为geoJson
const kmlToGeoJson = (file: UploadRawFile) => {
    let reader = new FileReader()
    reader.readAsText(file)
    return new Promise((resolve, reject) => {
        reader.onload = (e) => {
            // @ts-ignore 读取文件内容
            const fileString = e.target.result
            let geoJson = kml(new DOMParser().parseFromString(fileString as string, "text/xml"))
            resolve(geoJson)
        }
        reader.onerror = () => {
            ElMessage.error('kml文件读取失败')
            reject(reader.error)
        }
    })
}

// shapefile插件 shp转geo
const shpToGeoJson = async (data: ArrayBuffer) => {
    try {
        return await shp(data)
    } catch (e) {
        ElMessage.error('shp文件读取失败')
    }
}

const readShp = (file: UploadRawFile) => {
    let fileReader = new FileReader();
    fileReader.readAsArrayBuffer(file);
    return new Promise((resolve, reject) => {
        fileReader.onload = async (e) => {
            let fileString = e.target?.result
            let geoJson = fileString && await shpToGeoJson(fileString)
            geoJson && resolve(geoJson)
            geoJson || reject()
        }
        fileReader.onerror = () => {
            ElMessage.error('shp文件读取失败')
            reject(fileReader.error)
        }
    })
}


// 处理压缩包
const dealZip = async (file: UploadRawFile) => {
    const newZip = new JsZip()
    const res = await newZip.loadAsync(file)
    const fileList = Object.keys(res.files)
    const pattern = new RegExp(/\S\.shp$/)
    let shpFile = fileList.find(i => pattern.test(i))
    try {
        // @ts-ignore
        let res = await newZip.file(shpFile).async('arraybuffer')
        return await shpToGeoJson(res)
    } catch (err) {
        ElMessage.error('shp文件读取失败')
    }
}


// 处理文件
export const dealFile = async (file: UploadFile) => {
    let geoJson = undefined
    if (!file?.raw) return
    try {
        if (file?.name?.includes('.kml')) geoJson = await kmlToGeoJson(file.raw)
        else if (file?.name?.includes('.shp') || file?.name?.includes('.zip')) geoJson = await readShp(file.raw)
        else if (file?.name?.includes('.zip')) geoJson = await dealZip(file.raw)
        else ElMessage.warning(`本系统暂只支持${fileType}文件`)
    } catch (err) {
    }
    return geoJson
}

解析kml shp内的附带字段

1.shp的附带值是features[i].properties里的 基本不需要处理

2,kml附带值 在features[i].properties?.description?.value里  是个html格式的文本字段 里面的字段包裹在trtd 里面

let modifyTheDivOfTheValue: HTMLElement

function initUpload() {
    // 创建div 方便提前geoJson 值 创建一个div 并且一直使用一个div最后删除它
    modifyTheDivOfTheValue = document.createElement('div')
}

// 结束上传
function endUpload() {
    modifyTheDivOfTheValue?.remove?.()
}

// html  中获取tr td  数据并且转为对象格式
function conversion(html: string) {
    try {
        if (!html) return
        modifyTheDivOfTheValue.innerHTML = html
        // 获取所有  元素
        const rows = modifyTheDivOfTheValue.querySelectorAll('tr');
        // 初始化结果对象
        const result: any = {};
        // 遍历所有  元素
        rows.forEach(row => {
            // 获取当前  元素内的所有  元素
            const cells = row.querySelectorAll('td');
            // 检查  元素是否成对出现
            if (cells.length === 2) {
                // 将键值对添加到结果对象中 获取第一个  的文本内容作为键 获取第二个  的文本内容作为值
                result[cells[0].innerText] = cells[1].innerText
            }
        });
        return result
    } catch (err) {
        return ''
    }
}

循环geojson 值


    for (let i = 0; i < features?.length; i++) {
        let description = features[i].properties?.description?.value
    
        let result = conversion(description) 
    }

你可能感兴趣的:(地图,javascript,前端)