3D GIS 應(yīng)用開發(fā) —— 基于 Mapbox GL 的實(shí)踐總結(jié)

最近在折騰的 web 端的可視化項(xiàng)目,由于相關(guān)業(yè)務(wù)的需要,用到了 Mapbox 這一地圖開發(fā)的神器。在此先奉上一個(gè)基于mapbox-gl實(shí)現(xiàn)的demo(來源:uber的deck.gl項(xiàng)目):

demo

下面我們從這個(gè)項(xiàng)目一步步來介紹 Mapbox 的前端 GIS 引擎 Mapbox GL JS.

一、簡單了解

首先,Mapbox 在地圖領(lǐng)域是一家很 Newbee 的公司。已為 Foursquare、Pinterest、Evernote、金融時(shí)報(bào)、天氣頻道、優(yōu)步科技 等公司的網(wǎng)站提供了訂制在線地圖服務(wù)。

自2010年起,該公司快速地拓展了訂制地圖的市場地位,以回應(yīng) Google地圖 等地圖供應(yīng)商提供的有限選擇。Mapbox 是一些開放源代碼地圖庫及應(yīng)用程序的創(chuàng)建者或最大的貢獻(xiàn)者,其中包含了MBTiles 規(guī)范、TileMill 制圖 IDE、Leaflet JavaScript 庫,以及 CartoCSS 地圖格式化語言與語法分析器等。

該公司的數(shù)據(jù)同時(shí)從開放與專有的來源獲取,開放的數(shù)據(jù)源如 開放街圖(OSM, Open Street Map) 以及 NASA 等,而專有的數(shù)據(jù)源則包含了 DigitalGlobe。其技術(shù)奠基于 Node.js、CouchDB、Mapnik、GDAL 與 Leafletjs。

[圖片上傳失敗...(image-e27a1b-1515395418070)]

Mapbox 針對不同平臺均開發(fā)了相應(yīng)的 GIS 引擎以滿足開發(fā)者或相關(guān)用戶的需要,如:iOS SDK(用于iOS端開發(fā))、Android SDK(用于Andriod端開發(fā))、Navigation SDK(用于Navigation端開發(fā))、Unity SDK(用于Unity端開發(fā))、GL JS(用于web端開發(fā))。不同平臺的SDK,除使用方式不同外,功能特性上也多多少少存在不同。此外,Uber還針對react開發(fā)了 react-map-gl??偟膩碚f,Mapbox的開源技術(shù)棧是非常全面的。

二、輕松上手

[圖片上傳失敗...(image-426b0b-1515395418070)]

mapbox-gl 的 文檔 由 API、Style Specification、Example、Plugins 四部分內(nèi)容組成。

顧名思義,API 是一般框架(類庫)提供給用戶的全部接口(方法)的說明書;Style Specification 是 Mapbox 地圖的樣式規(guī)范;Example 是一些常用功能或常見業(yè)務(wù)的代碼示例,囊括了使用 Mapbox 所能實(shí)現(xiàn)的大部分功能效果;Plugins 則是官方推薦的可與 mapbox-gl 一同使用的一些增效插件和開源項(xiàng)目,如一些第三方的UI控件、顯示類插件、框架集成工具、開發(fā)輔助工具、實(shí)用工具類庫等等。

對于初了解 Mapbox 的童鞋,建議先從官網(wǎng)的 Example 入手,能夠較快掌握 mapbox-gl 的使用并投入開發(fā)實(shí)踐。

三、快速實(shí)踐

下面以文章開頭展示的項(xiàng)目為主,介紹其實(shí)戰(zhàn)步驟。

1. 加載地圖:

由于使用在線地圖服務(wù)和 style 時(shí)需要驗(yàn)證用戶 token,所以在使用 mapboxgl 時(shí)需要先配置用戶 token(在Mapbox官網(wǎng)注冊用戶即可獲取)。

import mapboxgl from 'mapbox-gl';
mapboxgl.accessToken = '<Your Token Here>';

接下來使用創(chuàng)建地圖實(shí)例。主要配置項(xiàng)如下:

const myMap = new mapboxgl.Map({
  container: '<Id of Container Element>',
  style: '<Your Style Here>',
  center: [112.508203125, 37.97980872872457],
  zoom: 4,
  pitch: 0,
  bearing: 0,
});

其中,container 是地圖容器的元素 id,style 是地圖樣式的 url,或者你自己定義的 style(需遵循Mapbox樣式規(guī)范),center 是地圖加載后默認(rèn)的中心點(diǎn)位置,用以定位地圖加載時(shí)的位置。zoom pitch bearing 分別指縮放級別、地面法線偏移角、地軸偏移角等,用以確定當(dāng)前視窗所顯示的地圖區(qū)域和空間關(guān)系。配置項(xiàng)的意義均可查看官網(wǎng)文檔。

2. 繪制圖形

這里主要介紹視頻中的3D建筑、飛線動畫等是如何實(shí)現(xiàn)的。這里以相關(guān)代碼片段來介紹實(shí)踐的方法。

在Mapbox中繪制圖形時(shí), layersource 是最重要的一組概念,后者用于存儲圖形的數(shù)據(jù)內(nèi)容,前者則是圖形在3D場景中的表現(xiàn)(圖層)。在Mapbox中,圖層一旦被創(chuàng)建,與其同名(id相同)的數(shù)據(jù)源源(即source)也必然被創(chuàng)建。反之,也可以在創(chuàng)建source后再創(chuàng)建一個(gè)圖層使用這個(gè)已創(chuàng)建的數(shù)據(jù)源,這時(shí)數(shù)據(jù)源與圖層間并不要求同名。而我們通過改變數(shù)據(jù)來驅(qū)動圖形變化,便是才去的第二種方式:

// 創(chuàng)建id為buildings的數(shù)據(jù)源
myMap.addSource('buildings', {
 type: 'geojson',
 data: '<GeoJson Contents>',
});

// 使用buildings的數(shù)據(jù)來繪制id為building_layer的圖形
myMap.addLayer({
  id: 'building_layer',
  type: 'fill-extrusion',
  source: 'buildings',
  ...<Other Options>,
});

基于上面的方式,當(dāng)數(shù)據(jù)改變時(shí),我們只需要重設(shè)數(shù)據(jù)源的數(shù)據(jù),即可驅(qū)動圖層重繪:

if (myMap.getLayer('building_layer')) {
  myMap.getSource('buildings').setData(<New GeoJson Contents>);
}

至于3D效果及動畫的具體實(shí)現(xiàn),這里給出兩個(gè)官網(wǎng)上的示例,相信大家能一目了然:

i. 用3D形式呈現(xiàn)建筑
ii. 給路徑中的一個(gè)點(diǎn)添加動畫效果

3. 圖形交互

Mapbox提供的交互方法是比較靈活的,活學(xué)活用API文檔便能實(shí)現(xiàn)各種炫酷、實(shí)用的交互效果。比如:使用
myMap.on('zoom', callback) 可以將圖形與地圖的縮放相綁定,當(dāng)縮放系數(shù)小于某個(gè)值時(shí),可以隱藏掉一些圖形元素:

myMap.on('zoom', () => {
  if (myMap.getZoom() <= 4) {
    myMap.setLayoutProperty('building_layer', 'visibility', 'none');
  } else {
    myMap.setLayoutProperty('building_layer', 'visibility', 'visible');
  }
});

再比如,連續(xù)調(diào)用 myMap.flyTo() 的方法使視圖在地圖上按照一定的軌跡緩慢移動,可以給用戶一種模擬飛行的體驗(yàn)。視頻中的自動巡視的效果正是這樣實(shí)現(xiàn)的。

諸如 click mouseover popup 等效果,官網(wǎng)文檔中的示例已經(jīng)具體呈現(xiàn),這里就不詳細(xì)展開了。

4. tiles-server的本地化

由于 Mapbox 地圖服務(wù)使用 MBTiles 存儲數(shù)據(jù),目前很多地圖服務(wù)都接受了這套標(biāo)準(zhǔn)(如:OSM,Open Street Map)。所以可以通過搭建自己的 tiles-server 以替代直接使用 Mapbox 的在線地圖服務(wù)。

這樣做的好處是顯而易見的:一是可以通過負(fù)載均衡等手段提高數(shù)據(jù)接口的訪問速度,有效提高數(shù)據(jù)的加載速度;一是保障應(yīng)用能在零帶寬的環(huán)境下仍能有效部署和使用。

這里墻裂安利一個(gè)docker開源鏡像:openmaptiles-server ,在其 官網(wǎng)dockerhub 上均可下載。個(gè)人認(rèn)為其最大的亮點(diǎn)在于——即使不了解內(nèi)部實(shí)現(xiàn),也不影響其使用。

openmaptiles.com

運(yùn)行 tiles-server 服務(wù)的 docker 命令如下:

$ docker run --rm -it -v $(pwd):/data -p 8080:80

然后剩下來需要做的事情就是打開其導(dǎo)航頁面 http://localhost:8080/(端口號取決于你的啟動命令),然后跟著頁面上的提示一步一步設(shè)置就好了(最后一步設(shè)置后會從OSM走動下載地圖,所以一開始你不用擔(dān)心數(shù)據(jù)從哪來),完全是傻瓜式的部署。

四、性能調(diào)優(yōu)

在 Mapbox GL 實(shí)踐的過程中,發(fā)現(xiàn)了一些影響應(yīng)用整體性能的因素,故而在此陳述一番,為之后填坑的童鞋提供一些經(jīng)驗(yàn):

  1. 使用geo數(shù)據(jù)(如 GeoJson 格式數(shù)據(jù))來定義圖形的時(shí)候,若數(shù)據(jù)量過大,則會拖慢數(shù)據(jù)加載的速度,此時(shí)可考慮:

i. 在 http 請求前后對數(shù)據(jù)進(jìn)行合理的壓縮和解壓,以盡可能節(jié)省 http 請求傳輸?shù)臄?shù)據(jù)量;
ii. 條件允許的情況下,可將一組數(shù)據(jù)分片加載,以空間換時(shí)間。

  1. 在 Mapboox 中繪制的圖層不宜過多,一是不方便管理(當(dāng)然,github上有很多管理Mapbox圖層的第三方工具),一是圖層過多會明顯降低GL的渲染和響應(yīng)性能。所以在繪制圖形前,可以先考慮一下圖層的劃分,以最少的圖層實(shí)現(xiàn)盡可能多的效果。

  2. 數(shù)據(jù)量相同的情況下,使用 mapboxgl.Marker 來添加標(biāo)記,其性能不如使用 typesymbol 類型的圖層來添加標(biāo)記。原因在于前者生成的標(biāo)記是一個(gè)個(gè) DOM 元素,如果你可以想象在一個(gè) web 頁面中同時(shí)操作成百上千個(gè) DOM 節(jié)點(diǎn)會是什么結(jié)果,那么你或許能明白我的建議。

五、一點(diǎn)總結(jié)

最后,在此總結(jié)下個(gè)人對 Mapbox 的一些感觀。

Mapbox 的產(chǎn)品定位是隨時(shí)隨地的 GIS(跨平臺、應(yīng)用),它為我們提供了一系列的簡單操作的 API,使得 GIS 開發(fā)變得靈活而有趣。尤其對于開發(fā) GIS 類型的數(shù)據(jù)可視化應(yīng)用,Mapbox 是絕佳的選擇。

然而,如果你只是為了那些絢麗的 3D 效果的話,或許選擇專門的框架更為合適。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,733評論 25 709
  • 從小在農(nóng)村生活,看到大人們見面打招呼 ,第一句話往往是“您吃飯了嗎“,小時(shí)候不解,怎么每個(gè)人、什么時(shí)候見面都問這句...
    長弓一箭閱讀 536評論 0 0
  • 我用自己的方式,祭奠自己的故事…… 在時(shí)針分針的奔跑中漸入夢鄉(xiāng),那里有一個(gè)開始,也有一個(gè)結(jié)束,或喜或憂,不過,醒來...
    jeremy馮閱讀 426評論 0 1
  • Andorid 寫 View 的時(shí)候總會遇到滑動沖突問題,解決 View 的滑動沖突是十分重要的,因此需要對 An...
    風(fēng)信子丶閱讀 593評論 0 4
  • 有一句話,闡述了道理, 規(guī)則越多的游戲,贏起來越容易, 人生的苦難在于它沒有規(guī)律, 越是試圖尋找,越是容易被算計(jì)。...
    釋迦干屎橛閱讀 433評論 0 2

友情鏈接更多精彩內(nèi)容