Mapbox使用笔记
什么是 mapbox
近期公司有一个在地图上展示大量数据的项目。需要可以在国内访问国外的地图,同时可以累加开发
最后我们找到了一个相当靠谱但是也比较复杂的地图库,就是 mapbox
就记录一下自己看过和用过的吧
mapbox 中国也有文档,但是不是最新的,不过可以参考
mapbox GL 应该怎么用
假设想搞出来这样一个东西,一个可以操作的地图上,有上亿的数据需要显示,这时候 mapbox gl 就非常合适
前端需要做的是根据mapbox gl js
的文档完成地图上的一些交互功能,比如地图控件,地图层的控制,地图的缩放移动事件等等。后端需要准备一份数据,毕竟那么多的点点不是随机生成的呀,具体的细节我不太清楚,就只放一份文档在这里。地图的层数据,甚至地图的样式,都是一个链接。前端拿到这个链接之后就可以获取到数据,按照 mapbox 的约定将数据呈现地图里
先把地图搞出来
上手最快的方法,就是看Examples
正确引入地图的 script 和 link 之后,和绝大多数地图一样,接管一个 html 元素,把地图 new 出来就可以了
1 | <link |
1 | // 哦对了,还要记得设置accsessToken |
mapbox GL 的一些概念
这关系到怎么去使用 mapbox 的功能
只说一些简单常用的
复杂的拎出来单独写写
Map,也就是 new mapboxgl.Map
主要的作用是初始化地图,得到一个地图的实例
传入参数,确定地图最初的样子
得到这个地图实例之后,就可以操作很多事情了
控件(Controls)
地图的控件,也就是地图的缩放按钮,导航按钮,比例尺之类的东西
这些都很简单啦
1 | // 关键方法 |
地图的限制(Constraints)
主要用来获得一些地图的属性,或者对地图进行一些选项设置
列举几个常用的方法
1 | map.getMinZoom(); |
地图的状态(Movement state)
地图是否正在移动,是否正在缩放,是否正在旋转
1 | map.isMoving(); |
标记(Markers)
在地图上做一个点标记
1 | const marker = new mapboxgl.Marker({ |
地图事件和事件的挂载卸载(events & working with events)
挂在和卸载地图的事件用的是map.on
, map.off
, map.once
第一个参数是事件名,比如 click,第二个参数是地图的层 id,类似于指定事件的 target,第三个参数是时间触发的函数(listener)
1 | // 缩放结束事件 zoomend |
生命周期(Lifecycle)
地图的生命周期函数,比如加载之后触发一个事件,出错了的事件…
常用的是 load
1 | const map = new mapboxgl.Map({}); |
还有 error
1 | const map = new mapboxgl.Map({}); |
图片(images)
给地图里面添加图标之类的东西,需要先loadImage
然后addImage
然后再loadImage
的 callback 中继续
loadImage 的第一个参数是图片的链接,或者 base64,第二个参数是回调
addImage 的第一个参数是给图片一个名字,第二个参数是图片,第三个参数是一些选项
The image as an HTMLImageElement , ImageData , ImageBitmap or object with width , height , and data properties with the same format as ImageData
1 | // 需要在地图层中加载图片 |
使用的时候
1 | "layout": { |
地图上的弹窗(popup)
地图上点击某个点打开一个泡泡框是常见的需求,地图提供了一个泡泡框的类
1 | const layer_id = "LayerId"; |
一些复杂的,或者更重要的
- 数据源和地图层(source & layer)
- 数据源的 type
- 表达式(Expressions)
数据源和地图层
在地图上显示各种不同的信息,每个信息都是一个层(layer),地图是由多个层组成的。而层依赖于数据,没有数据源,就无法生成一个层。
数据源(Source)
https://docs.mapbox.com/mapbox-gl-js/api/sources/
https://docs.mapbox.com/mapbox-gl-js/style-spec/sources/
数据源为地图层提供了数据,没有数据,层的显示毫无意义。
addSource 的第一个参数是这个数据源的 id,层通过这个 id,可以使用到数据源
Source 的 type 是 vector 时,url 的值就是后端给的。而 geojson 是一份静态资源
1 | map.addSource("colleges", { |
地图层(Layer)
地图层是依附于地图基底(style)上的,在使用map.setStyle()
之后,地图层就会被清空。同时,地图层依赖于数据源。
数据源也可以作为一个选项卸载 addLayer 中。
数据源的 type 是vector
时,source-layer
是必选参数
1 | map.addLayer({ |
每个层都有一个 id,可以通过这个 id 对层进行控制,比如隐藏掉一个地图层
1 | map.setLayerProperty("LayerId", "layer_option", "value"); |
数据源的 type
目前后端给到的 source 有两种,第一种是GeoJSON
,另一种是Vector
在 mapbox 里,不同的 source 有不同的功能,比如 GeoJSON 可以聚合,而 Vector 就不可以
GeoJSON
顾名思义,GeoJSON 是一个关于地理数据的一个 JSON 格式
在 mapbox 里,GeoJson 可以使用聚合(cluster)显示的功能,可以看这个例子
GeoJSON 它是可以是一个文件,也可以是 json 字符串,但是读取都在前端。所以无法避免被爬取。如果是比较小的数据,可以用这个格式
Vecter
Vector 是托管在 mapbox 服务器上的,是一个通过算法压缩过的数据格式,可以用来传输大量的位置点。比如这个美国人种分布的散点图例子
Vector 类型不支持聚合,但是可以通过 Layer 的minzoom
和maxzoom
控制显示。
表达式(Expressions)
表达式是 Mapbox 的一个特色了,哇,这个用起来好复杂的,但是做内容匹配很方便
表达式的语法很简单,就是一个 JavaScript 数组,这个数组的每个元素都有特别的意义,数组会返回一个值。其本质是个 JavaScript 函数
1 | // 这里以表达式的rgb方法为例,写一个类似的JavaScript函数 |
表达式可以嵌套,因为表达式返回的是一个值,这个值当然可以作为参数
1 | // 还以rgb为例,做一个计算过的rgb |
部分表达式可以访问到数据源,匹配出合适的结果,下面的这个paint['circle-color']
属性中,使用了 match 表达式,第二个参数从数据集中选择了数据源,之后第三个参数是匹配到的值,第四个参数是遇到这个属性显示的颜色。就好像switch case
。而最后一个#f9e33e
是一个默认值。就好像switch case default
1 | 'paint': { |
利用表达式,可以做很多奇妙的事情,比如不同的值显示不同的颜色(上面的)。甚至切割加工字符串,过滤掉某些值等等