最近折腾的web端可视化项目,因相关业务需要,使用了地图开发神器Mapbox。这里有一个基于mapbox-gl的demo(来源:uber的deck.gl项目):从这个项目开始,我们一步步介绍Mapbox的前端GIS引擎MapboxGLJS。1.简单理解首先,Mapbox在地图领域是一家很Newbee的公司。已为Foursquare、Pinterest、Evernote、FinancialTimes、TheWeatherChannel、UberTechnology等公司网站提供定制化在线地图服务。自2010年以来,该公司迅速扩大了其在自定义地图领域的市场份额,以应对谷歌地图等地图提供商提供的有限选项。Mapbox是多个开源地图库和应用程序的创建者或最大贡献者,包括MBTiles规范、TileMill地图IDE、LeafletJavaScript库以及CartoCSS地图格式化语言和解析器。该公司的数据来自公开和专有来源,公开来源包括开放街道地图(OSM,OpenStreetMap)和NASA,以及专有来源包括DigitalGlobe。它的技术基于Node.js、CouchDB、Mapnik、GDAL和Leafletjs。Mapbox针对不同平台开发了相应的GIS引擎以满足开发者或相关用户的需求,例如:iOSSDK(用于iOS开发)、AndroidSDK(用于Andriod开发)、NavigationSDK(用于导航开发)、UnitySDK(用于Unity端开发)、GLJS(用于web端开发)。不同平台的SDK除了使用方法不同外,功能特性也有些不同。此外,Uber还为React开发了react-map-gl。总的来说,Mapbox的开源技术栈非常全面。2.易于上手mapbox-gl的文档由四个部分组成:API、StyleSpecification、Example和Plugins。顾名思义,API就是通用框架(类库)向用户提供的所有接口(方法)的描述;StyleSpecification是Mapbox地图的样式规范;大部分功能效果;Plugins是官方推荐的可以和mapbox-gl一起使用的插件和开源项目,比如一些第三方UI控件、显示插件、框架集成工具、开发辅助工具、实用工具类库等.对于刚刚接触Mapbox的小朋友,建议先从官网的Example入手,这样可以快速掌握mapbox-gl的使用,并投入到开发实践中。3.快速实践下面以文章开头展示的项目为基础,介绍实战步骤。1.加载地图:由于使用在线地图服务和样式需要验证usertoken,所以在使用mapboxgl时需要先配置usertoken(可以在Mapbox官网注册用户获取)。importmapboxglfrom'mapbox-gl';mapboxgl.accessToken='';接下来,使用创建地图实例。主要配置项如下:constmyMap=newmapboxgl.Map({container:'<容器元素的Id>',style:'<你的样式>',center:[112.508203125,37.97980872872457],zoom:4,间距:0,轴承:0,});其中container是地图容器的元素id,style是地图样式的url,或者你自己定义的样式(需要遵循Mapbox样式规范),center是地图加载后默认的中心点位置,用于定位地图加载时的位置。zoompitchbearing分别指缩放级别、地面法线偏移角、地轴偏移角等,用于确定当前窗口显示的地图区域和空间关系。配置项的含义可以查看官网文档。2.绘制图形这里主要介绍视频中的3D建筑和飞线动画是如何实现的。下面是相关的代码片段来介绍实用的方法。在Mapbox中绘制图形时,层和源是最重要的概念。后者用来存储图形的数据内容,前者是图形在3D场景中的表示(图层)。在Mapbox中,一旦创建了图层,还必须创建同名(相同id)的数据源(source)。反之,也可以在创建源后创建层来使用创建的数据源。此时,数据源和图层之间不需要重名。然后我们更改数据来驱动图形变化,这是第二种方式://创建一个id为建筑物的数据源myMap.addSource('buildings',{type:'geojson',data:'',});//使用建筑物的数据绘制id为building_layer的图形myMap.addLayer({id:'building_layer',type:'fill-extrusion',source:'buildings',...,});基于上述方法,当数据发生变化时,我们只需要重新设置数据源的数据即可驱动图层重绘:setData();}至于3D效果和动画的具体实现,这里有官网的两个例子,相信大家一眼就能看懂:以3D形式呈现建筑物ii.给路径3.图形交互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()方法,让view按照一定的轨迹在地图上缓慢移动,可以给用户模拟飞行的体验。视频中自动巡视的效果就是这样实现的。对于点击mouseover弹窗等效果,官网文档中的示例已经有详细介绍,这里不再赘述。4.tiles-server的本地化由于Mapbox地图服务使用MBTiles来存储数据,目前很多地图服务都接受这个标准(例如OSM,OpenStreetMap)。因此您可以构建自己的tiles-server而不是直接使用Mapbox的在线地图服务。这样做的好处是显而易见的:首先,可以通过负载均衡等方式提高数据接口的访问速度,有效提高数据加载速度;首先是确保应用程序在零带宽环境下仍然可以有效部署和使用。这里安利WallCrack的一个docker开源镜像:openmaptiles-server,可以在其官网和dockerhub上下载。个人认为它最大的亮点是——即使你不了解内部实现,也不影响它的使用。运行tiles-server服务的docker命令如下:$dockerrun--rm-it-v$(pwd):/data-p8080:80剩下就是打开它的导航页面http://localhost:8080/(端口号取决于你的启动命令),然后按照页面提示一步步设置(最后一步设置后,会从OSM下载地图,所以你没有一开始就担心数据从哪里来),完全是傻瓜部署。4.性能调优在MapboxGL实践过程中,发现了一些影响应用整体性能的因素,所以在此声明一下,为后面补齐的童鞋们提供一些经验:使用geo数据(如作为GeoJson格式的数据)来定义图形时,如果数据量太大,会减慢数据加载的速度。这时,你可以考虑:i.合理压缩和解压http请求前后的数据,尽可能节省http请求传输的数据量;二.在条件允许的情况下,可以将一组数据分段加载,以空间换取时间。在Mapboox中绘制的图层不应该太多。一是不方便管理(当然github上有很多管理Mapbox图层的第三方工具),二是图层太多会明显降低GL的渲染和响应性能。因此,在绘制图形之前,可以先考虑图层的划分,用最少的图层达到尽可能多的效果。在数据量相同的情况下,使用mapboxgl.Marker添加标记不如使用类型为symbol的图层添加标记。原因是前者生成的标记是DOM元素。如果你能想象一下在一个网页中同时操作成百上千个DOM节点的结果,那么你可能会理解我的建议。5.一点总结最后在这里总结一下个人对Mapbox的一些印象。Mapbox的产品定位是随时随地的GIS(跨平台、应用),它为我们提供了一系列易于操作的API,让GIS开发变得灵活有趣。特别是对于开发GIS类型的数据可视化应用程序,Mapbox是一个极好的选择。不过,如果你只是追求那些绚丽的3D效果,或许选择专用相框更为合适。