故事 | Uber 如何做地理信息数据可视化?附案例源码
你知道吗?Uber的开源工具 Deck.gl 和 Mapbox GL JS 经常被组合使用,可以创建炫酷的地理信息可视化效果。
Deck.gl 的 MapView 可以与 Mapbox 协同工作, 两个库中相同的相机设置(中心,缩放,间距和方位)可以进行无缝匹配, 在几乎所有的地理空间数据应用程序中,Mapbox都被用作 deck.gl 可视化层的背景。
这为更紧密集成的地理空间可视化开辟了许多新的可能性。
例如,可以在Mapbox的基础地理和标签图层之间插入 deck.gl GeoJSON 图层,这样填充的多边形不再妨碍地图的可读性; Deck.gl 的弧形图层和Mapbox的建筑物图层可以同时出现在城市的空域,3D 元素也可以正确地相互遮挡。
deck.gl 和 Mapbox gl js单独使用原理
deck.gl 和 Mapbox gl js结合使用原理
具体来说,Uber在deck.gl的V6.2版本中推出了新的模块@deck.gl/mapbox, 您可以到Github上研究开源代码,也可以继续看下面的快速上手教程。
全新的实验类MapboxLayer是Mapbox GL JS的自定义图层界面的实现,我们可以使用nmp导入。
npm install @deck.gl/mapbox
import {MapboxLayer} from ‘@deck.gl/mapbox’;
或者使用 deck.gl standalone bundle。
<script src=”https://unpkg.com/deck.gl@^6.2.0/deckgl.min.js"></script>
<script src=’https://api.tiles.mapbox.com/mapbox-gl-js/v0.50.0/mapbox-gl.js'></script>
<script type=”text/javascript”>
const {MapboxLayer} = deck;
</script>
MapboxLayer的实例可以通过map.addLayer()加载到Mapbox图层中。这一步,官网有详细的教程。
使用deck.gl图层作为Mapbox附加组件
您可以使用deck.gl的图层目录中的任何图层类型及其相应的道具制作MapboxLayer:
import {ScatterplotLayer} from '@deck.gl/layers';
import {MapboxLayer} from '@deck.gl/mapbox';
import mapboxgl from 'mapbox-gl';
// Get a mapbox API access token
mapboxgl.accessToken = '<your access token here>';
// Initialize mapbox map
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v9',
center: [-74.50, 40],
zoom: 9
});
// Create a mapbox-compatible deck.gl layer
const myDeckLayer = new MapboxLayer({
id: 'my-scatterplot',
type: ScatterplotLayer,
data: [
{position: [-74.5, 40], size: 10000}
],
getPosition: d => d.position,
getRadius: d => d.size,
getColor: [255, 0, 0]
});
// Insert the layer before mapbox labels
map.on('load', () => {
map.addLayer(myDeckLayer, 'waterway-label');
});
请注意:以这种方式使用时,不支持基于WebGL2的deck.gl功能,例如属性转换和GPU加速聚合。
将Mapbox添加到deck.gl React应用程序
修改正在工作的deck.gl React应用,并集成Mapbox并不难,下面是简单的步骤:
将应用程序的react-map-gl依赖项升级到版本4.0.0-beta。 这个版本允许我们提供为Mapbox创建的deck.gl的WebGL环境。
像往常一样将图层传递到<DeckGL />组件中。
加载Mapbox地图时,我们通过引用deck.gl堆栈中现有图层的ID来创建MapboxLayers并将其添加到Mapbox中。
import React from 'react';
import DeckGL, {ScatterplotLayer} from 'deck.gl';
import {StaticMap} from 'react-map-gl';
import {MapboxLayer} from '@deck.gl/mapbox';
const INITIAL_VIEW_STATE = {
longitude: -74.50,
latitude: 40,
zoom: 9
};
export class App extends React.Component {
state = {};
// DeckGL and mapbox will both draw into this WebGL context
_onWebGLInitialized = (gl) => {
this.setState({gl});
}
// Add deck layer to mapbox
_onMapLoad = () => {
const map = this._map;
const deck = this._deck;
map.addLayer(new MapboxLayer({id: 'my-scatterplot', deck}), 'waterway-label');
}
render() {
const {gl} = this.state;
const layers = [
new ScatterplotLayer({
id: 'my-scatterplot',
data: [
{position: [-74.5, 40], size: 10000}
],
getPosition: d => d.position,
getRadius: d => d.size,
getColor: [255, 0, 0]
})
];
return (
<DeckGL
ref={ref => {
// save a reference to the Deck instance
this._deck = ref && ref.deck;
}}
layers={layers}
initialViewState={INITIAL_VIEW_STATE}
controller={true}
onWebGLInitialized={this._onWebGLInitialized}
>
{gl && (
<StaticMap
ref={ref => {
// save a reference to the mapboxgl.Map instance
this._map = ref && ref.getMap();
}}
gl={gl}
mapStyle="mapbox://styles/mapbox/light-v9"
mapboxApiAccessToken="<your access token here>"
onLoad={this._onMapLoad}
/>
)}
</DeckGL>
);
}
}
📖
几个案例
就像在文章《Custom Layers | 一行代码生成炫酷的可视化地图,别错过这款 Uber 开源工具》中提到的那样,这样的可视化方案已经集成到了实际案例中,例如:
可视化英国的道路交通事故情况
该可视化案例描绘了1979年至2016年英国的人身伤害交通事故。它使用deck.gl的HexagonLayer来汇总每个六边形单元边界内的数据。 HexagonLayer插入Mapbox的标签图层下方。
这个案例比较突出的地方是3D拉伸,为可视化显示新增了维度。
可视化美国的县城迁徙情况
该可视化案例显示了2009 - 2013年间美国的县到县迁移。 将鼠标悬停在地图上可查看进出特定区域的人员。 它使用自定义的deck.gl图层,根据鼠标位置过滤弧线。这个案例比较突出的地方是弧线轨迹绘制,之前并没有很好的工具支持这一点。
案例源码9a46f
不妨跟着上面的案例,一起学习一下Uber的可视化效果吧,感受如何将地理空间数据可视化扩展新的维度:更灵活、更轻量、更美观。
如果你还是觉得比较晕,不妨尝试一下这个Uber官方的Demo。
👀相关阅读
数据可视化5个例子,Atlas 帮你的数据在私有云上「自由可视化」
刚刚!亚马逊 Alexa Auto 集成了 Mapbox 地图和导航服务
您还可以在下面的渠道持续关注我们哦。
微博
@Mapbox地图数据平台,或者tag #mapbox#
知乎
@Mapbox中国