天天看點

前端加載shapefile資料 | WebGIS

前端加載本地shapefile格式檔案轉成geojson格式資料,本文将通過介紹兩個開源utils進行展示

一、加載​

​.shp​

​​|​

​.dbf​

​格式檔案

1.安裝依賴

npm install shapefile --save-dev      

​​https://github.com/mbostock/shapefile​​

2.使用

const loadShp = () => {
    // 建立input标簽
    let input = document.createElement('input');
    input.type = 'file';
    input.accept = ".shp"
    input.onchange = e => {
        let file = e.target.files[0];
        let [name,format] = file.name.split('.');
        if (file?.size / 1024 / 1024 > 10) {
            alert("請選擇内容小于10MB的檔案!")
        }
        if ('.shp'.includes(format)) {
            let fileReader = new FileReader();
            fileReader.readAsArrayBuffer(file);
            fileReader.onload = function () {
                let shapefile = require('shapefile');
                shapefile.read(this.result).then((geojson) => {
                    console.log("shp加載", geojson);
                    addGeoJsonToMap(geojson, name)
                });
            }
        } else {
            alert("暫不支援該類型資料檔案")
        }
    }
    input.click();
}      

3.效果

這個讀取隻能讀取幾何資訊并轉成geojson格式,至于坐标系還是屬性資訊,都是讀取不到的

前端加載shapefile資料 | WebGIS

但是我們可以使用​

​openDbf​

​​方法單獨讀取​

​dbf​

​格式檔案

點選檢視代碼

const loadDbf = () => {
    // 建立input标簽
    let input = document.createElement('input');
    input.type = 'file';
    input.accept = ".dbf"
    input.onchange = e => {
        let file = e.target.files[0];
        let [name, format] = file.name.split('.');
        if (file?.size / 1024 / 1024 > 10) {
            alert("請選擇内容小于10MB的檔案!")
        }
        if ('.dbf'.includes(format)) {
            let fileReader = new FileReader();
            fileReader.readAsArrayBuffer(file);
            fileReader.onload = function () {
                let shapefile = require('shapefile');
                shapefile.openDbf(this.result).then((geotable) => {
                    console.log("dbf加載", geotable);
                });
            }
        } else {
            alert("暫不支援該類型資料檔案")
        }
    }
    input.click();
}      
前端加載shapefile資料 | WebGIS

二、加載shapefile所有檔案壓縮成​

​.zip​

​格式的檔案

1.安裝依賴

npm install shpjs --save-dev      

​​https://github.com/calvinmetcalf/shapefile-js​​

2.使用

const loadZip = () => {
    // 建立input标簽
    let input = document.createElement('input');
    input.type = 'file';
    input.accept = ".zip"
    input.onchange = e => {
        let file = e.target.files[0];
        let [name, format] = file.name.split('.');
        if (file?.size / 1024 / 1024 > 10) {
            alert("請選擇内容小于10MB的檔案!")
        }
        if ('.zip'.includes(format)) {
            let fileReader = new FileReader();
            fileReader.readAsArrayBuffer(file);
            fileReader.onload = function () {
                let shapefile = require('shpjs/dist/shp');
                shapefile.parseZip(this.result).then((geojson) => {
                    console.log("zip加載", geojson);
                    addGeoJsonToMap(geojson, name)
                });
            }
        } else {
            alert("暫不支援該類型資料檔案")
        }
    }
    input.click();
}      

3.效果

可以看到,加載打包成zip格式的shapefile檔案,在這裡可以讀取到幾何資訊和屬性資訊,但坐标依舊是讀取不到

前端加載shapefile資料 | WebGIS

值得注意,這個zip加載好像會把坐标轉成4326的坐标

如圖,shp格式本來是3857坐标系的,打包成zip用這個庫解析後,變成了4326的坐标系了

// proj4js包将坐标從4326轉換為3857
import Proj4 from "./proj4.js";      
前端加載shapefile資料 | WebGIS

不想轉成4326的話,我趕時間暫時如下處理,有想法的自行去鑽研了

// 把這個shp.js檔案14479行改成如下格式,因為它會把坐标轉換成4326,本系統預設坐标3857
// parsed = shp.combine([parseShp(zip[name + '.shp'], zip[name + '.prj']), dbf]);
// ==>> parsed = shp.combine([parseShp(zip[name + '.shp']), dbf]);      

​​JS 讀取本地Shp的壓縮包(zip)轉換為geojson​

前端加載shapefile資料 | WebGIS

三、其它

如圖,我們可以知道這個檔案的路徑

前端加載shapefile資料 | WebGIS
前端加載shapefile資料 | WebGIS

那麼我們可以直接把這個檔案複制出來,放到拓展檔案夾下(這裡可以把檔案改名)

前端加載shapefile資料 | WebGIS

用的時候,直接引用

前端加載shapefile資料 | WebGIS

另外一個庫也是如此!

(2022-11-11) 好像不行,它有其它的依賴庫o(╥﹏╥)o~~,單獨用的話,還需要下載下傳齊它的依賴庫.

arcgis api加載geojson資料至地圖

​geojsonToArcGIS​

​是把geojson的feature格式轉出arcgis的geometry格式的一個方法

我用的是Arcgis for js 4.24版本,直接調用下面的方法,就可以把圖層加載至地圖了

​​geojsonToArcGIS()是一個arcgis-to-geojson-utils庫裡方法,更多詳情請點選檢視​​

// 添加geojson檔案圖層
const addGeoJsonToMap = (geoJson, name) => {
    // 圖形集
    let graphics = [];
    // 圖形類型
    let layerStyleType;
    // 圖形渲染
    let symbol;
    switch (geoJson.features?.at(0).geometry.type ?? 'Polygon') {
        case 'Point':
            symbol = {
                type: "simple-marker",
                color: 'rgba(226, 119, 40)',
                outline: {
                    color: 'rgba(255, 255, 255)',
                    width: 2
                }
            }
            layerStyleType = 'point';
            break;
        case 'LineString':
            symbol = {
                type: "simple-line",
                color: 'rgba(227, 139, 79, 0.8)',
                width: 3,
                cap: "round",
                join: "round"
            }
            layerStyleType = 'polyline';
            break;
        case 'Polygon':
        case 'MultiPolygon':
            symbol = {
                type: "simple-fill",
                color: 'rgba(227, 139, 79, 0.8)',
                outline: {
                    color: 'rgba(255, 255, 255)',
                    width: 1
                }
            }
            layerStyleType = 'polygon';
            break;
        default:
            console.log('default');

    }
    if (!layerStyleType) return;
    geoJson.features.forEach(value => {
        let graphic = geojsonToArcGIS(value);
        graphic.geometry.spatialReference = new SpatialReference({ wkid: 3857 });
        graphic.geometry.type = layerStyleType;
        graphic.symbol = symbol;
        graphics.push(graphic)
    })
    let layer = new GraphicsLayer({
        title: name,
        graphics,
        symbol,
        layerStyleType,
        spatialReference: new SpatialReference({ wkid: 3857 }),
        attributes
    })
    map.layers.add(layer);
    // 縮放至于該圖層
    layer.when(() => {
        let geometries = layer.graphics.items.map(e => e.geometry);
        let g = geometryEngine.union(geometries);
        if (g) {
            view.goTo(g).catch((error) => {
                console.error(error);
            });
        }
    })
}