覽編輯器開源:一個純前端實現(xiàn)的拆解)
背景日常處理行政區(qū)劃、POI、軌跡等 GeoJSON 數(shù)據(jù)時經(jīng)常需要先看一眼邊界畫得對不對、坐標系是不是 WGS84、字段結(jié)構(gòu)是否符合預(yù)期。常見的做法是把文件傳到在線工具或者打開一個完整的桌面 GIS。前者有數(shù)據(jù)外泄的顧慮后者對于一個看一眼的需求又太重。我們把 GeoJSONcn 站點里的預(yù)覽編輯器抽出來做成了一個不依賴任何后端的純前端工具并開源出來。它解決什么問題本地打開 GeoJSON 即可渲染數(shù)據(jù)不上傳服務(wù)器支持要素級的查看與編輯能把同一份數(shù)據(jù)導(dǎo)出成 GeoJSON / KML / SVG / CSV / PNG對接不同的下游系統(tǒng)不需要npm install不需要構(gòu)建雙擊index.html就能用。技術(shù)實現(xiàn)渲染Leaflet 與坐標系核心就是用地圖庫把 GeoJSON 畫出來。下面是一段最小可用的加載代碼// 初始化地圖并加載一份 GeoJSON// 要素量大時把渲染器從默認 SVG 換成 Canvas避免 DOM 節(jié)點過多卡頓constmapL.map(map,{renderer:L.canvas()}).setView([39.9,116.4],4);L.tileLayer(https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png,{attribution:? OpenStreetMap}).addTo(map);fetch(example.geojson).then(rr.json()).then(geojson{L.geoJSON(geojson,{style:{color:#2563eb,weight:1.5},onEachFeature:(feature,layer){constnamefeature.propertiesfeature.properties.name;if(name)layer.bindPopup(name);}}).addTo(map);});這里有個容易混淆的點Leaflet 的地圖視圖默認使用 Web MercatorEPSG:3857投影但Feature 的坐標本身仍是 EPSG:4326WGS84Leaflet 在加載時會自動完成經(jīng)緯度到墨卡托的轉(zhuǎn)換開發(fā)者無需手動處理。需要提醒的是本項目只處理 WGS84 數(shù)據(jù)。國內(nèi)的地圖數(shù)據(jù)常?;煊?GCJ-02火星坐標系或 BD-09本項目目前沒有內(nèi)置糾偏邏輯如果拿到的數(shù)據(jù)偏移明顯需要先自行糾偏再導(dǎo)入。計算Turf.js要素的幾何操作計算包圍盒、合并、切分、面積量算等交給 Turf.js。本倉庫把 Turf 以本地文件形式打包在turf/目錄里頁面里直接通過全局turf對象調(diào)用無需打包工具// 用 Turf 計算要素包圍盒與面積turf 為倉庫內(nèi)置的全局對象constbboxturf.bbox(geojson);// [minX, minY, maxX, maxY]constareaturf.area(geojson);// 單位平方米console.log(包圍盒:,bbox,面積(㎡):,area);預(yù)覽頁里切分選中要素這類能力就是從主站編輯器移植過來的底層依賴 Turf 的幾何運算。導(dǎo)出管線幾種導(dǎo)出格式各自有幾個容易踩坑的技術(shù)點// KML 坐標順序是 經(jīng)度,緯度,海拔注意和 GeoJSON 的 [lon, lat] 對應(yīng)多一個高程// 多環(huán) / 多維坐標需要遞歸處理functioncoordsToKml(coords){if(typeofcoords[0][0]number){returncoords.map(c${c[0]},${c[1]},0).join( );}returncoords.map(coordsToKml).join( );}// 導(dǎo)出 CSV 時在開頭寫入 BOM避免 Excel 打開中文亂碼constcsvname,lon,lat\nrows.join(\n);constblobnewBlob([\uFEFFcsv],{type:text/csv;charsetutf-8;});GeoJSON最直接把內(nèi)存里的 FeatureCollection 序列化即可注意保留properties與坐標系聲明。KML需要按DocumentPlacemarkPolygonouterBoundaryIsLinearRingcoordinates的結(jié)構(gòu)組織坐標順序經(jīng)度,緯度,海拔轉(zhuǎn)換時別寫反見上。SVG把[經(jīng)度, 緯度]用等距圓柱投影線性映射到viewBox的像素坐標輸出path dM x y L x y Z。投影本身很簡單難點在視口自適應(yīng)和描邊寬度的處理。CSV每個要素一行屬性平鋪成列字段含中文且要進 Excel 時文件開頭需帶 BOMEF BB BF否則中文亂碼見上。PNG把當前渲染結(jié)果繪制到canvas后用toBlob/toDataURL導(dǎo)出圖片。目錄結(jié)構(gòu)geojson-preview/ ├── index.html # 入口頁說明 主站入口 ├── preview.html # 預(yù)覽編輯器本體 ├── leaflet/ # 地圖渲染引擎 ├── turf/ # 幾何計算 ├── vendor/ # 其他第三方依賴 ├── LICENSE # MIT ├── NOTICE └── README.md整個項目是靜態(tài)文件沒有打包步驟依賴都以本地文件形式存在leaflet/、turf/、vendor/目錄里??焖匍_始# GitHubgitclone https://github.com/laukuo/geojson-preview.git# Giteegitclone https://gitee.com/SmartMailer/geojson-preview.git克隆后用瀏覽器直接打開index.html即可無需安裝依賴、無需啟動服務(wù)。與 GeoJSONcn 主站的關(guān)系這個倉庫是 GeoJSONcn全國行政區(qū)劃邊界矢量數(shù)據(jù)下載平臺預(yù)覽功能的獨立開源版。主站還提供省、市、區(qū)縣、鄉(xiāng)鎮(zhèn)街道四級行政區(qū)劃邊界數(shù)據(jù)的在線預(yù)覽與下載你也可以直接在 在線預(yù)覽頁 體驗完整功能開源版把輕量預(yù)覽 編輯 導(dǎo)出這一段單獨拆了出來方便在自己的項目里直接集成或做二次開發(fā)。二次開發(fā)與集成幾種常見的接入方式在自己的頁面里直接引用本倉庫的leaflet/與turf/復(fù)用渲染與計算邏輯把preview.html以iframe的形式嵌到內(nèi)部系統(tǒng)里本地加載 GeoJSON 時優(yōu)先用FileReader讀取用戶選定的文件而不是fetch本地路徑——后者在file://協(xié)議下會受到瀏覽器同源策略限制// file:// 下用 FileReader 讀本地文件避開 fetch 的同源限制constinputdocument.getElementById(file);input.addEventListener(change,(){constreadernewFileReader();reader.onloaderenderGeoJSON(JSON.parse(e.target.result));reader.readAsText(input.files[0]);});開源地址代碼基于 MIT 協(xié)議發(fā)布同時托管在 GitHub 與 GiteeGitHubhttps://github.com/laukuo/geojson-previewGiteehttps://gitee.com/SmartMailer/geojson-preview歡迎在倉庫里提 Issue 和 PR。相關(guān)鏈接開源倉庫GitHubhttps://github.com/laukuo/geojson-preview開源倉庫Giteehttps://gitee.com/SmartMailer/geojson-preview項目主站https://geojsoncn.com/在線預(yù)覽https://geojsoncn.com/preview.html