Mapbox矢量切片源码分析

为了了解矢量切片的更多技术细节,轻微挖一挖Mapbox-gl-js的前端结构。比较关键的内容是矢量切片如何在前端如何被定义、加载和绘制,下面结合源码稍微介绍下。

概念

矢量切片规范

Mapbox矢量切片规范定义的内容:文件格式(后缀名、MIME)、投影和范围、内部结构(图层、要素、几何图形编码、要素属性)。切片文件里不在是地理坐标(例如经度和纬度),而是屏幕坐标,也并不包含任何地理信息。在切片文件里,原点坐标是左上角,x轴向右递增,y轴向下递增。

绘制

Mapbox-gl-js使用客户端绘制,这是vector tiles在前端最核心的部分,也因为此,在前端运行时修改地图样式变得轻而易举。大多数地图前端SDK或api(如arcgis、openlayers、leaflet),决定mapview的通常就是center point + zoom level(或 center point + extent),在矢量绘制情况下,zoom level可以是任意的,包括小数(例如6.5),应该基本上算是无极缩放了。除此之外,还有两个很重要的参数:
1. bearing:地图旋转参数,单位是度数。
2. pitch:地图倾斜角度(3d才cool嘛)。

在图层方面,Mapbox gl中定义了渲染数据的方式,这些数据即可以是栅格,也可以是矢量。但由于前端渲染,所以实际上底图和专题图在技术实现上,并没有实质的区别。这样的好处是,所有的要素都可以如同arcgis下的GraphicLayer,或者Javascript中的div一般可拥有较可控的交互能力。

camera和Map

Mapboxgl.camera控制目标位置的中心点位置、缩放级别、旋转角度和倾斜角度。Mapboxgl.Map对象是提供开发接口的最基本对象,继承自camera,并在初始化的时候通过container的设置(HTML元素)来告知Mapboxgl渲染出对应的Map对象。

下面是加载一个mapboxgl地图的例子:

style、source和layer

无所不包的style

也许因为可视化是第一要务,所以Mapbox定义了style这么个概念,也是一切配置的总结点,也是通过JSON对象来进行配置,并需要遵守Mapbox样式规范,或者通过URL来获取这个JSON。

典型的style节点结构如下:

Mapbox构造自己的生态,所以若直接使用Mapbox的数据,即从它的API获取style,可以直接:

毕竟,Mapbox需要的就是用什么数据,绘成什么样子。当然,目前这并不是我们关注的重点。从包含内容来说,style包含很多内容,比较重要的例如version、center、zoom、bearing、pitch、light、sources、layers等。而这其中,sources和layers又最为重要。可以这样说,style是所有信息的总入口,里边可以定义地图的各种绘制信息和参数,最重要的是可以定义数据源(矢量、栅格、视频、图像等),而layers则定义了最终需要渲染的内容,这是一个逻辑上的“图层”,这个“图层”会定义与绘制相关的具体细节,以及要引用哪些sources。Vector Tile能够在前端任意改变样式,重组数据,都是基于这样的style->sources->layers结构。

下面看下sources部分的源代码,layers部分暂时不予讨论,比较明确,可以直接参看:mapbox-gl-style-spec#layers

sources(数据源)

通过定义矢量切片数据源,让api知晓瓦片来自何处,对于mapbox的sample普通用户,底图数据来自mapbox的服务器,因此对于底图来说,往往只定义style就可以了。此外,需要注意的是,添加source并不能直接直接在前端显示数据,具体的layers中对图层的定义,才是与可视化渲染相关。看一下mapbox-gl-js的源码,source type主要有这么几种:

source的作用,就是通过参数选项来创建一个切片数据源的实例。每个数据源,都必须有唯一id,用于标识数据源。除此之外的内容,可以来看下最主要的三类数据源的构造函数

VectorTile数据源

vector tile的tilesize必须是512,默认定义了0-22的zoom level,另外,最主要的两个参数是url和tiles。url指向一个TileJSON的地址,支持三中协议:http,https,mapbox。而tiles是一个数组,指向多个TileJSON。对于TileJSON的描述如下:

TileJSON is a format for describing tilesets. It keeps track of where to request the tileset, the name of the tileset, and any attribution that’s necessary when using the tileset.

geojson数据源

例如下面的示例通过data指向一个网络url(M1.0+地震数据) ,并创建一个heatmap。当然,实际使用中,data也可以直接是语义正确的geojson对象。

渲染结果如下: