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