Mapbox 入门初试
Mapbox入坑初试,建筑物拉起以及点击高亮
mapbox 是一个优秀的 2D、3D 地图库,它提供精美的地图服务以及高效的地图渲染方式。map 使用 webGL 渲染地图,可以动态修改地图样式,满足不同的需求
# 1. Mapbox 中 layer 和 source 的关系
mapbox 使用数据来驱动图层的,和其他的如 leaflet,openlayer 这类地图库不一样,除了底图之外,其他的图层都需要提供 source 图层,layer 根据 source 作为数据进行渲染。每一个 layer 和 source 都需要有一个 id,通过 id 名称来进行区分。一个 layer 对应一个 source,但是通一个 source 可以对应多个 layer。这样就方便对数据进行分层管理,可以将 source 中不同类别的数据展示在不同的 layer 中。 mapbox 支持的 source 有这些:vector, raster, raster-dem, geojson, image, video. 例如:加载 geojson 数据:
map.addSource('geoData', {
type: 'geojson',
data: data
})
2
3
4
mapbox 没有提供加载文件的功能,所以如果是从文件中加载的话,需要自己写 XHR 请求,然后再设置 source,例如,从文件中加载 geojson 可以这么写:
fetch('./data/data.geojson')
.then(resp => resp.json())
.then(data => {
//调用addSource方法
})
2
3
4
5
# 2.mapbox 中的 paint
paint 属性用来设置 mapbox 图层的绘制规则,这是 mapbox 的精华所在,mapbox 文档有专门一栏讲解样式设置 (opens new window)的,这里面可以设置绘制面的颜色,填充色,透明度等等,而且还可以通过一些逻辑判断来设置不同的属性,十分灵活和复杂。建议通过官网来学习
# 3.mapbox 拉起建筑物以及点击建筑物高亮示例
map.on('load', function() {
// 请求geojson数据
fetch('./data/data.geojson')
.then(resp => resp.json())
.then(data => {
// 加载图片作为建筑物纹理,异步方法
map.loadImage('./data/texture.jpg', (err, image) => {
// 纹理加载
map.addImage('texture', image)
// 设置数据源,由于原数据中没有id属性,由 mapbox生成唯一ID值
map.addSource('geoData', {
type: 'geojson',
data,
generateId: true
})
// 建筑物贴图
map.addLayer({
id: '3d-build',
// 设置数据源
source: 'geoData',
type: 'fill-extrusion',
// 只显示属性值building==yes的数据
filter: ['==', 'building', 'yes'],
// 缩放级别大于15级显示
minzoom: 15,
paint: {
// 拉升高度通过属性值height获取
'fill-extrusion-height': ['to-number', ['get', 'height']],
'fill-extrusion-base': 0,
'fill-extrusion-opacity': 1,
// 设置纹理
'fill-extrusion-pattern': 'texture'
}
})
// 建筑物顶部
map.addLayer({
id: 'buildTop',
// 数据源
source: 'geoData',
type: 'fill-extrusion',
// 针对建筑物
filter: ['==', 'building', 'yes'],
minzoom: 15,
paint: {
// 填充颜色根据状态切换
'fill-extrusion-color': [
'case',
['boolean', ['feature-state', 'hover'], true],
'#aaa',
'red'
],
// 起始高度和拉升高度相同,则只是顶部的面被处理
'fill-extrusion-height': ['to-number', ['get', 'height']],
'fill-extrusion-base': ['to-number', ['get', 'height']],
'fill-extrusion-opacity': 1
}
})
// 点击事件
let hoverId = null
map.on('click', '3d-build', e => {
if (e.features.length > 0) {
// hoverId为空,表示是初次点击
if (!hoverId) {
// 获取要素ID,根据数据值和id设置状态
hoverId = e.features[0].id
map.setFeatureState({ source: 'geoData', id: hoverId }, { hover: false })
} else {
map.setFeatureState({ source: 'geoData', id: hoverId }, { hover: true })
hoverId = null
}
}
})
})
})
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
代码效果如下:
在线示例可前往 http://zhouzhili.github.io/demo/mapbox-3d-build/ (opens new window) 查看