前段時間參與了一個項目,客戶有一個功能需求是上傳SHP文件並在地圖上顯示,然後在此基礎上做緩衝區處理。經過對比測試,最終選擇了shapefile.js工具,在此做個記錄。
shapfe.js能夠將Esri的Shapefile文件轉換爲GeoJSON,它能夠以Shapefile文件zip的壓縮文件和單獨的.shp文件作爲輸入參數。
shapefile.js安裝
項目是基於Vue開發的,因此選擇了npm的安裝方式,安裝非常簡單,執行下面的命令就可以了。
npm install shpjs
獲取上傳的SHP文件
在HTML中可使用type爲file的input標籤獲取上傳的.shp文件或者壓縮後的Shapefile文件。
<input type="file" id="uploadFileInput" name="zip" @change="selectShpFile()">
selectShpFile: function() {
this.shpFile = document.getElementById("uploadFileInput").files[0];
}
使用FileReader處理上傳後的SHP文件
JavaScript中的FileReader用來讀取Blob或者File的內容。
FileReader共包含4個方法,其中三個用來讀取文件內容,一個用來打斷讀取。
方法名稱 | 方法參數 | 方法描述 |
---|---|---|
abort | – | 中斷文件讀取 |
readAsBinaryString | File | 將文件讀取爲二級制碼 |
readAsDataURL | File | 將文件讀取爲DataURL |
readAsText | File, [encoding] | 將文件讀取爲文本 |
FileReader處理事件共有6個,具體描述如下:
事件名稱 | 事件描述 |
---|---|
onabort | 中斷時觸發 |
onerror | 出錯時觸發 |
onload | 文件讀取成功時觸發 |
onloadend | 讀取完成時觸發,無論成功或失敗 |
onloadstart | 讀取開始時觸發 |
onprogress | 讀取中 |
這裏需要注意的一點是,文件一旦開始讀取,無論成功還是失敗,實例的result屬性都會被填充,也就是說如果讀取失敗,result的值爲null,讀取成功則爲讀取的結果。
在本項目中,我們使用了readAsBinaryString方法,並且監聽onload事件獲取文件的讀取內容。
let fileReader = new FileReader();
fileReader.readAsArrayBuffer(shpFile);
fileReader.onload = function() {
// 獲取讀取的結果
console.log(this.result);
}
使用shapefile.js將SHP文件讀取爲GeoJSON
shapefile.js使用也非常簡單,我們使用其read方法,並將上一步的文件的二進制讀取結果作爲read方法的參數,然後在其回調函數中獲取GeoJson。
這一步和上一步的整合後的代碼如下:
let fileReader = new FileReader();
fileReader.readAsArrayBuffer(shpFile);
fileReader.onload = function() {
let shapefile = require("shapefile");
shapefile
.read(this.result)
.then(geoJson => {
console.log(geoJson);
}
}
GeoJSON文件內容如下圖所示:
在地圖中加載GeoJson
在地圖中加載GeoJson需要遍歷其features屬性,將其中的每個feature轉爲對應的幾何對象(點、線或者面),然後將轉換的幾何對象構建成一個Graphic,最後將Graphic添加到GraphicLayer中。
遍歷features,構建Polygon對象
geoJson.features.map(feature => {
const polygon = new EsriPolygon({
spatialReference: new EsriSpatialReference({ wkid: 2380 })
});
feature.geometry.coordinates.forEach(function(coord) {
const coordinates =
feature.geometry.type === "MultiPolygon" ? coord[0] : coord;
polygon.addRing(coordinates);
});
}
Polygon構建Graphic,並添加到GraphicLayer
let graphics = [];
let graphicsExtent = null;
geoJson.features.map(feature => {
const polygon = new EsriPolygon({
spatialReference: new EsriSpatialReference({ wkid: 2380 })
});
feature.geometry.coordinates.forEach(function(coord) {
const coordinates =
feature.geometry.type === "MultiPolygon" ? coord[0] : coord;
polygon.addRing(coordinates);
});
const graphic = new EsriGraphic({
geometry: polygon,
attributes: feature.properties,
symbol: {
type: "simple-fill", // autocasts as new SimpleFillSymbol()
color: [51, 51, 204, 0.9],
style: "solid",
outline: {
color: "white",
width: 1
}
}
});
graphics.push(graphic);
});
graphicLayer.addMany(graphics);
至此,我們已經完成了上傳並在地圖中展示SHP文件的整個流程,下一步就可以調用相應的API函數創建緩衝區,並執行接下來的各種功能。