最近在折騰的 web 端的可視化項目,因爲相關業務的須要,用到了 Mapbox 這一地圖開發的神器。在此先奉上一個基於mapbox-gl實現的demo短片(來源:uber的deck.gl項目):前端
下面咱們從這個項目一步步來介紹 Mapbox 的前端 GIS 引擎 Mapbox GL JS.react
首先,Mapbox 在地圖領域是一家很 Newbee 的公司。已爲 Foursquare、Pinterest、Evernote、金融時報、天氣頻道、優步科技 等公司的網站提供了訂製在線地圖服務。git
自2010年起,該公司快速地拓展了訂製地圖的市場地位,以迴應 Google地圖 等地圖供應商提供的有限選擇。Mapbox 是一些開放源代碼地圖庫及應用程序的建立者或最大的貢獻者,其中包含了MBTiles 規範、TileMill 製圖 IDE、Leaflet JavaScript 庫,以及 CartoCSS 地圖格式化語言與語法分析器等。github
該公司的數據同時從開放與專有的來源獲取,開放的數據源如 開放街圖(OSM, Open Street Map) 以及 NASA 等,而專有的數據源則包含了 DigitalGlobe。其技術奠定於 Node.js、CouchDB、Mapnik、GDAL 與 Leafletjs。web
Mapbox 針對不一樣平臺均開發了相應的 GIS 引擎以知足開發者或相關用戶的須要,如:iOS SDK(用於iOS端開發)、Android SDK(用於Andriod端開發)、Navigation SDK(用於Navigation端開發)、Unity SDK(用於Unity端開發)、GL JS(用於web端開發)。不一樣平臺的SDK,除使用方式不一樣外,功能特性上也多多少少存在不一樣。此外,Uber還針對react開發了 react-map-gl。總的來講,Mapbox的開源技術棧是很是全面的。docker
mapbox-gl 的 文檔 由 API、Style Specification、Example、Plugins 四部份內容組成。json
顧名思義,API 是通常框架(類庫)提供給用戶的所有接口(方法)的說明書;Style Specification 是 Mapbox 地圖的樣式規範;Example 是一些經常使用功能或常見業務的代碼示例,囊括了使用 Mapbox 所能實現的大部分功能效果;Plugins 則是官方推薦的可與 mapbox-gl 一同使用的一些增效插件和開源項目,如一些第三方的UI控件、顯示類插件、框架集成工具、開發輔助工具、實用工具類庫等等。api
對於初瞭解 Mapbox 的童鞋,建議先從官網的 Example 入手,可以較快掌握 mapbox-gl 的使用並投入開發實踐。微信
下面以文章開頭展現的項目爲主,介紹其實戰步驟。負載均衡
因爲使用在線地圖服務和 style
時須要驗證用戶 token
,因此在使用 mapboxgl
時須要先配置用戶 token
(在Mapbox官網註冊用戶便可獲取)。
import mapboxgl from 'mapbox-gl';
mapboxgl.accessToken = '<Your Token Here>';
複製代碼
接下來使用建立地圖實例。主要配置項以下:
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樣式規範),center
是地圖加載後默認的中心點位置,用以定位地圖加載時的位置。zoom
pitch
bearing
分別指縮放級別、地面法線偏移角、地軸偏移角等,用以肯定當前視窗所顯示的地圖區域和空間關係。配置項的意義都可查看官網文檔。
這裏主要介紹視頻中的3D建築、飛線動畫等是如何實現的。這裏以相關代碼片斷來介紹實踐的方法。
在Mapbox中繪製圖形時, layer
和 source
是最重要的一組概念,後者用於存儲圖形的數據內容,前者則是圖形在3D場景中的表現(圖層)。在Mapbox中,圖層一旦被建立,與其同名(id
相同)的數據源源(即source
)也必然被建立。反之,也能夠在建立source後再建立一個圖層使用這個已建立的數據源,這時數據源與圖層間並不要求同名。而咱們經過改變數據來驅動圖形變化,即是纔去的第二種方式:
// 建立id爲buildings的數據源
myMap.addSource('buildings', {
type: 'geojson',
data: '<GeoJson Contents>',
});
// 使用buildings的數據來繪製id爲building_layer的圖形
myMap.addLayer({
id: 'building_layer',
type: 'fill-extrusion',
source: 'buildings',
...<Other Options>,
});
複製代碼
基於上面的方式,當數據改變時,咱們只須要重設數據源的數據,便可驅動圖層重繪:
if (myMap.getLayer('building_layer')) {
myMap.getSource('buildings').setData(<New GeoJson Contents>); } 複製代碼
至於3D效果及動畫的具體實現,這裏給出兩個官網上的示例,相信你們能一目瞭然:
* i. 用3D形式呈現建築
* ii. 給路徑中的一個點添加動畫效果
Mapbox提供的交互方法是比較靈活的,活學活用API文檔便能實現各類炫酷、實用的交互效果。好比:使用 myMap.on('zoom', callback)
能夠將圖形與地圖的縮放相綁定,當縮放係數小於某個值時,能夠隱藏掉一些圖形元素:
myMap.on('zoom', () => {
if (myMap.getZoom() <= 4) {
myMap.setLayoutProperty('building_layer', 'visibility', 'none');
} else {
myMap.setLayoutProperty('building_layer', 'visibility', 'visible');
}
});
複製代碼
再好比,連續調用 myMap.flyTo()
的方法使視圖在地圖上按照必定的軌跡緩慢移動,能夠給用戶一種模擬飛行的體驗。視頻中的自動巡視的效果正是這樣實現的。
諸如 click
mouseover
popup
等效果,官網文檔中的示例已經具體呈現,這裏就不詳細展開了。
因爲 Mapbox 地圖服務使用 MBTiles 存儲數據,目前不少地圖服務都接受了這套標準(如:OSM,Open Street Map)。因此能夠經過搭建本身的 tiles-server 以替代直接使用 Mapbox 的在線地圖服務。
這樣作的好處是顯而易見的:一是能夠經過負載均衡等手段提升數據接口的訪問速度,有效提升數據的加載速度;一是保障應用能在零帶寬的環境下仍能有效部署和使用。
這裏牆裂安利一個docker開源鏡像:openmaptiles-server ,在其 官網 和 dockerhub 上都可下載。我的認爲其最大的亮點在於——即便不瞭解內部實現,也不影響其使用。
運行 tiles-server 服務的 docker 命令以下:
$ docker run --rm -it -v $(pwd):/data -p 8080:80
複製代碼
而後剩下來須要作的事情就是打開其導航頁面 http://localhost:8080/(端口號取決於你的啓動命令),而後跟着頁面上的提示一步一步設置就行了(最後一步設置後會從OSM走動下載地圖,因此一開始你不用擔憂數據從哪來),徹底是傻瓜式的部署。
在 Mapbox GL 實踐的過程當中,發現了一些影響應用總體性能的因素,故而在此陳述一番,爲以後填坑的童鞋提供一些經驗:
- 使用geo數據(如 GeoJson 格式數據)來定義圖形的時候,若數據量過大,則會拖慢數據加載的速度,此時可考慮:
i. 在 http 請求先後對數據進行合理的壓縮和解壓,以儘量節省 http 請求傳輸的數據量
ii. 條件容許的狀況下,可將一組數據分片加載,以空間換時間
- 在 Mapboox 中繪製的圖層不宜過多,一是不方便管理(固然,github上有不少管理Mapbox圖層的第三方工具),一是圖層過多會明顯下降GL的渲染和響應性能。因此在繪製圖形前,能夠先考慮一下圖層的劃分,以最少的圖層實現儘量多的效果。
- 數據量相同的狀況下,使用
mapboxgl.Marker
來添加標記,其性能不如使用type
爲symbol
類型的圖層來添加標記。緣由在於前者生成的標記是一個個 DOM 元素,若是你能夠想象在一個 web 頁面中同時操做成百上千個 DOM 節點會是什麼結果,那麼你或許能明白個人建議。
最後,在此總結下我的對 Mapbox 的一些感觀。
Mapbox 的產品定位是隨時隨地的 GIS(跨平臺、應用),它爲咱們提供了一系列的簡單操做的 API,使得 GIS 開發變得靈活而有趣。尤爲對於開發 GIS 類型的數據可視化應用,Mapbox 是絕佳的選擇。
然而,若是你只是爲了那些絢麗的 3D 效果的話,或許選擇專門的框架更爲合適。
關注微信公衆號:創宇前端(KnownsecFED),碼上獲取更多優質乾貨!