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