记一次前端揭开绘制地图的神秘面纱分享会
點擊上方?前端瓶子君,關注公眾號
回復算法,加入前端編程面試算法每日一題群
記錄了我在組內的技術分享, 有同樣需求的同學可以參考一下
分享全程下來時間大約 70分鐘
image一. 為什么要分享前端相關的"地圖"知識
(大屏展示)很多公司都會有相應的大屏幕展示系統, 例如中國或者全世界的客戶與資產分布圖.
(生動描繪)用地圖的角度來展示地理方面的關系, 讓人看著比單純的文字更直觀
(場景多)比如今年的各類疫情嚴重情況的分布圖.
總的來說還是看起來比較炫酷, 可以提升一點點b格, 并且這個只是也是屬于前端的范疇, 那么我們就有必要弄懂它.
二. 做地圖相關技術簡介
這里我只介紹幾款我常用的
** 百度地圖
這個名氣太大了, 功能很多并且現在對3d的支持也很不錯, 注意GL版v1.0 與之前 v2.0版本地圖的api有點不一樣別掉坑里.
缺點也比較明顯, 比如你想要一份干干凈凈的地圖, 上面沒有店鋪沒有任何標識的時候我就建議你用echarts來玩了, 因為百度地圖帶的東西比較多.
想要使用百度地圖的同學可以看這里, 超級簡單就可以完成注冊用玩耍.
使用非常簡單
** hcharts
非常牛非常好用, 但是它部分功能是要收費的, 使用之前要讓公司幫你買好相應的功能才能用于商用哦.
由于我們公司地圖庫是自己研發的最后也就沒有這種網上付費的.
詳情地址
** echarts
這個庫前端無人不知了, 在需求很簡單的情況下建議用這個技術來做, 大部分時候項目中需要繪制柱狀圖或折線圖的時候已經引入了echarts此時不用重復引用來節省空間.
echarts畫的地圖
** 我們公司自己的2d, 3d地圖組件庫
這個在這里就不做過多詳細介紹了, 一些公司也會有自主研發的地圖組件, 設計的思想上可能與上面三個不太相同, 接下來我也會聊到.
三.echarts實現基礎地圖
以echarts為例是因為這個最好弄...
這里我新建了一個vue工程
<template><div?class="home"><div?id="map"></div></div> </template><script> import?echarts?from?"echarts"; import?mapData?from?"./geo";export?default?{name:?"Home",data()?{return?{myChart:?null,};},methods:?{initMap()?{this.myChart?=?echarts.init(document.getElementById("map"));echarts.registerMap("world",?mapData);?//?定義名稱下面要用,?這樣做的好處就是可以很方便的實現切換地圖的效果this.myChart.setOption({series:?[{type:?"map",mapType:?"world",?//?自定義擴展圖表類型label:?{show:?false,},},],});},},mounted()?{this.initMap();} }; </script>像我們平時使用echarts一樣先初始化
接下來有點不同需要echarts.registerMap("world", mapData);?可以理解為把這個數據命名為'world', 方便以后的切換(這里的數據我下面會講).
在option的配置里面設置類型是地圖, 使用上面定義好的'world'類型.
效果圖
我們可以看得出來, 地圖的繪制也沒什么'特殊'的, 最主要的就是那個?mapData數據, 這個數據一般叫它geojson數據, 那么接下來我們認識一下它.
四.geojson數據到底是什么
geojson是用json的語法表達和存儲地理數據,可以說是json的子集, 它不是專門js使用的這點要清楚.
地圖上有山川, 河流, 海洋等等的地理信息, 那么如何描述一條河? 這個時候就要使用geojson格式的文件來描繪.
并不是必須用geojson, geojson只是一套規范, 各大解析器用這套規范來解析生成對應的景色, 我們完全可以制定自己的規范來實現這些, 無非是兼容性不好需要自己寫繪制的解析器.
五.geojson詳細介紹
英語好的可以先擼網站
1. 基本結構
以后我們看到"type": "FeatureCollection"這樣一行就說明這個文件是geojson規范的文件
2. 描述一個點(Feature)
地圖上的打點數據
3. 描述多個點(FeatureCollection)
**優點
寫法簡潔
這些點樣式可以共用
4. 描述一條線(LineString)
這里還是描繪每一個點, 但這些點會連接在一起形成線
地圖上的連線數據
5. 描述多條線(MultiLineString)
這里第二組與第一組的線, 可以分隔開不會首尾相連.
6. 描述一個面(Polygon, 也叫多邊形)
第一個點與最后一個點要相同, 這樣才能完成閉環!!
三維數組的格式需要注意
7. 一個面里面有多個面(Polygon)
這種單一的'Polygon'里面出現多個形狀, 會出現中空的情況, 類似布爾運算, 這樣就可以在地圖中描述那種圈型的國家
效果如下:
8. 描述多個面(MultiPolygon)
優勢:
寫法簡潔
這些點樣式可以共用
這里如果重疊了就是顏色的疊加了如圖所示:
9. 描述一個組(geometries)
比如我們為了表示一種特定的地貌那么我們可以把這個地貌數據獨立起來
10. 不同的樣式(properties)
{"type":?"FeatureCollection","features":?[{"type":?"Feature","properties":?{?//?專門放屬性"stroke":?"#fa9661",?//?外邊顏色"stroke-width":?4.1,?//?外邊寬"stroke-opacity":?0.7,?//?外邊透明度"fill":?"#9e290c",??//?填充色"fill-opacity":?0.7?//?填充色透明度},"geometry":?{"type":?"Point",??//?畫點"coordinates":?[105.380859375,?31.57853542647338]}},] }六. geojson的相關網站與工具的使用
** 展示干巴巴的數據大家看著不起勁, 這里我推薦一個繪制geojson的超棒網站地址
那么我來介紹一下如何使用這個網站高效的生成, 以及調試geojson
也就是最后生成的geojson, 這里的變化可以實時影響圖像, 并且會有錯誤提示很方便編寫.
繪制直線
繪制多邊形也就是面, 這里注意要首位相連.
繪制矩形, 這里應該是專門封裝的方法繪制矩形.
繪制點, 這里會為我們在地圖上mark一下, 具體的圖片需要我們自己在項目中引用.
點擊之后進入編輯模式, 鼠標在圖形上會出現小手標識, 此時可以拖動圖形移動, 操作可以選擇是否保留.
刪除模式, 點擊可以刪除指定圖形,操作可以選擇是否保留.
單擊圖形可以出現如圖所示的操作框.
添加樣式屬性, 上方展示的是當前樣式屬性
保存你的更改
刪除這個圖形
點擊open可以使用本地的geojson文件進行導入繪制.
save下面點擊geojson可以把生成的代碼文件下載到本地.
七.自制geojson解析繪制工具的思路
我們可以只做一個轉換器, 也就是你隨便寫認為不錯的格式, 最后轉換成geojson的格式.
直接用你喜歡的格式來繪制圖形
如果用canvas來實現就是繪制對應的圖形就好了, 就是圖形疊加那里需要特殊處理一下, 樣式直接讀取properties里面的數據進行設置.
繪制經緯度也是個問題, 畢竟在平面上不好計算經緯度(接下地圖繪制章節會講相關知識).
所以綜上看來是不是繪制一張平面版的地圖也沒那么困難, 只要數據對了就成功一小半了.
八.地圖的基本概念 (瓦片地圖, 矢量地圖)
** 有沒有發現咱們使用的地圖在放大的時候,區域都是一個方塊一個方塊的被加載成圖像的.
** 如果你打開控制臺的network還可以看到有好多png的請求.
** 地圖這種超大的數據, 超多細節是如何做到快速渲染的?
** 下面是現在比較主流的兩種地圖的繪制模式.
柵格瓦片地圖
顧名思義圖片像是瓦片一樣堆疊起來的格子狀成為地圖, 有點像拼圖, 是不是感覺一點也不高大上....
但這里也是有很多問題要解決的, 比如你在俯視世界的視角看地圖, 那么出現的就是世界的瓦片圖片, 當高度小于一定的數值時就采用另一套相應的瓦片, 在某個高度范圍內是采用放大瓦片圖片的方式模擬視野的下降, 每次請求瓦片圖片都需要傳遞: 1: 當前視口所在坐標(經緯度) 2: 當前視口寬高 3: 當前視角高度.
柵格瓦片以 256?256 或 512?512 大小的圖片為介質,這種技術通常是在服務端預先將圖片渲染好,前端根據地圖的縮放等級,按需加載圖片加以拼接,目前依舊在大規模使用,但這種方式存在一些劣勢:
受到網絡帶寬開銷和存儲空間限制的影響大,離線化部署成本高,單套主題將近 500 多 G(中國)。
樣式編輯完后端渲染需要時間長。
無三維的建筑數據,在 3D 場景中無高度信息。
數據保密性差。
矢量地圖
顧名思義就是矢量繪制出圖形, 只要不是照片肯定會小很多, 對于矢量為什么輕量并且不失真可以參考的上篇文章svg的分享svg實戰
矢量瓦片采用和柵格瓦片相同的分級切割方案,不同的是,瓦片數據傳輸的是地理數據,包括道路、土地、建筑等,通過在前端做地圖的渲染,具有如下優勢:
極少占用服務器空間,降低網絡開銷,本地化部署只需5G空間(中國)。
地圖的底圖樣式更換簡單.
因為具有了地理數據本身,可在數據基礎上做三維空間的延伸,例如 3D 建筑。
數據保密性強。
九.不同的坐標系
** 地球本身是個橢球體, 要把它以平面的方式繪制在一個矩形上也真的不好辦, 現在有不少繪制的方式但是都有各自的優缺點, 感興趣的朋友可以查查看具體的細節, 我這里就簡單介紹下比較常見的方式.
經緯度EPSG:4326 也就是地圖的默認坐標
現在球體上定義好經緯度, 然后在正方形紙上畫出刻度, 對應的繪制
墨卡托投影(EPSG:3785 )
把地球放在一個圓筒里面, 假設地球內部有個光源, 那么地球在圓柱上的投影就是地圖
火星坐標系
火星坐標是國家測繪局為了國家安全在原始坐標的基礎上進行偏移得到的坐標,基本國內的電子地圖、導航設備都是采用的這一坐標系或在這一坐標的基礎上進行二次加密得到的。
火星坐標的真實名稱應該是 GCJ-02 坐標,基本上所有的國內的電子地圖采用的都是火星坐標系甚至 Google 地圖中國部分都特意為中國政府做了偏移。
百度坐標系
火星坐標是在國際標準坐標 WGS-84 上進行的一次加密,由于國內的電子地圖都要至少使用火星坐標進行一次加密,百度直接就任性一些,直接自己又研究了一套加密算法,來了個 二次加密,這就是我們所熟知的百度坐標 BD-09,當然只有百度地圖使用的是百度坐標
WGS-84 坐標系
GS-84 坐標是一個國際的標準,一般衛星導航,原始的 GPS 設備中的數據都是采用這一坐標系。國外的 GoogleMap、OpenStreetMap、MapBox、OpenLayer 等采用的都是這一坐標。
geojson設置坐標系
由于坐標系的不同, 那么就算繪制一個點的坐標也都不會完全相同了, 那么就需要我們來告訴使用geojson的人按哪種坐標系進行解析
使用上線的規則
{"type":?"FeatureCollection","crs":?{"type":?"link",?//?這里變成了link"properties":?{"href":?"http://example.com/crs/42",?//?這里是你設置的資源鏈接"type":?"proj4"?//?"proj4","ogcwkt",esriwkt"?只能這三種格式}},"features":?[{},] }?十.更快的前端數據 -> WebAssembly
**WebAssembly是一種新的編碼方式,文件體積更小,啟動速度更快,運行速度也更快,與使用JavaScript構建的Web應用相比,性能提升明顯。它是多種編程語言的編譯器目標,包括C++、C、Rust等。
WebAssembly 是由主流瀏覽器廠商組成的 W3C 社區團體 制定的一個新的規范。**
WebAssembly 可以明顯的提升計算的速率, 還挺適合用在地圖庫里面的
WebAssembly 和 JavaScript 結合使用, 短時間并不會替代js
.wasm文件結尾的文件來標識.
WebAssembly 有一套完整的語義,實際上 wasm 是體積小且加載快的二進制格式, 其目標就是充分發揮硬件能力以達到原生執行效率
WebAssembly 運行在一個沙箱化的執行環境中,甚至可以在現有的 JavaScript 虛擬機中實現。在web環境中,WebAssembly將會嚴格遵守同源策略以及瀏覽器安全策略。
WebAssembly 設計了一個非常規整的文本格式用來、調試、測試、實驗、優化、學習、教學或者編寫程序??梢砸赃@種文本格式在web頁面上查看wasm模塊的源碼。
WebAssembly 在 web 中被設計成無版本、特性可測試、向后兼容的。WebAssembly 可以被 JavaScript 調用,進入 JavaScript 上下文,也可以像 Web API 一樣調用瀏覽器的功能。當然,WebAssembly 不僅可以運行在瀏覽器上,也可以運行在非web環境下。
解析 - 解碼 WebAssembly 比解析 JavaScript 要快
編譯和優化 - 編譯和優化所需的時間較少,因為在將文件推送到服務器之前已經進行了更多優化,JavaScript 需要為動態類型多次編譯代碼
重新優化 - WebAssembly 代碼不需要重新優化,因為編譯器有足夠的信息可以在第一次運行時獲得正確的代碼
執行 - 執行可以更快,WebAssembly 指令更接近機器碼
垃圾回收 - 目前 WebAssembly 不直接支持垃圾回收,垃圾回收都是手動控制的,所以比自動垃圾回收效率更高。目前瀏覽器中的 MVP(最小化可行產品) 已經很快了。在接下來的幾年里,隨著瀏覽器的發展和新功能的增加,它將在未來幾年內變得更快。
說了這些都是概念, 接下來我們就一起實戰一下go
十一. hello 級別的WebAssembly
中文官網
官網的實現還需要配置環境啥的搞得很正式, 入門級別其實我們更想的是嘗嘗鮮, 只要你會點c++就能用我接下來的方法實現.
在線生成
在線生成
點擊轉換c++代碼為WebAssembly格式
點擊下載轉換好的文件
下載到的是個二進制文件
引用文件
?fetch("/test.wasm").then((res)?=>?res.arrayBuffer())?//?拿到Buffer格式.then((bytes)?=>?WebAssembly.compile(bytes))?//?轉字節碼.then((mod)?=>?{const?instance?=?new?WebAssembly.Instance(mod);const?exp?=?instance.exports;console.log(exp._Z7showNumv())});exp._Z7showNumv 而不是 exp.showNum, 這個我們可以在Wat那一欄修改一下, 但是代碼多了修改起來也不容易應該有禁止轉換時修改名稱的選項這里就不過多展開了.
注意這里會跨域, 因為屬于文件協議, 你可以本地啟個服務.
開發成本
需要的不只是前端技術了.
bug稍微有點多, 比如不好調試, 還有的同學遇到了每次編譯結果不同等問題.
社區不完善
建議這門技術先使用在封裝度較高, 計算量很大的模塊上.
十二.(組內篇)我寫的2d與3d工程的代碼介紹
這里我在組內展示一下我編寫的兩個項目的代碼結構與遇到的問題, 就不在這里展開了畢竟涉及保密問題, 但大體思路就是把地圖分成世界, 國家, 省, 市, 區 幾個等級(省市區是中國的分法), 相當于一個狀態機, 然后在每個狀態下做相應的事比如打點與連線, 每次變換圖層狀態都會隱藏其他圖層展示相應視野的圖層.
end.
地圖方面也屬于前端比較有用的一環, 我今年剛接觸地圖相關項目也是一臉蒙, 但是詳細學習了geojson等知識之后再用地圖相關組件庫就非常順暢了.
這次就是這樣, 希望和你一起進步.
關于本文:
來源:lulu_up
https://segmentfault.com/a/1190000037611134
最后
歡迎關注【前端瓶子君】??ヽ(°▽°)ノ?
回復「算法」,加入前端編程源碼算法群,每日一道面試題(工作日),第二天瓶子君都會很認真的解答喲!
回復「交流」,吹吹水、聊聊技術、吐吐槽!
回復「閱讀」,每日刷刷高質量好文!
如果這篇文章對你有幫助,「在看」是最大的支持
?》》面試官也在看的算法資料《《
“在看和轉發”就是最大的支持
總結
以上是生活随笔為你收集整理的记一次前端揭开绘制地图的神秘面纱分享会的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Mindmanager2012安装图解
- 下一篇: html canvas保存为图片,在HT