mapbox-gl教程(3):添加自定义数据(小数据量的方式)(下)

示例的详细说明

我们先简单回顾一下上一章的demo:
要想展示自定义数据,我们需要先把数据做成数据源添加到map对象里,然后再新建一个图层指定样式和数据源添加到map。
所以在示例中,我们用构造了包含两个点的geojson数据源,然后构造了一个半径为20像素的红点样式,就完成了数据的展现工作。

接下来,我们详细了解一下geojson和样式的结构

geojson

这个网页详细介绍了geojson的标准;
这个网页对geojson标准进行了翻译。
总之很详细很复杂就是了。我们的应用中一般不需要这么复杂,所以这里对mapbox里geojson数据源的常用属性进行说明:

要素容器(FeatureCollection)

mapbox的geojson数据源,data部分要传入一个FeatureCollection,格式如下:

1
2
3
4
5
6
{
"type": "FeatureCollection",
"features": [
...//这里放要素
]
}

很简单,就是留出一个数组来放要素

要素

要素包含了形状(geometry)和属性(properties)

1
2
3
4
5
{
"type": "Feature",
"geometry": ...//这里放形状json,
"properties": ...//这里放属性
}

属性就是一个key-value格式的json,如{name:"张三",age:25}

形状则根据其类型的不同有不同的格式,这里介绍一下常见的点、线、面三种类型:

点形状(point)

在coordinates属性中放了一个长度为2的数组存放经纬度

1
2
3
4
{
"type": "Point",
"coordinates": [102.0, 0.5]//经纬度
}

线形状(LineString)

在coordinates属性中放了一组经纬度坐标存放线上每个点的经纬度

1
2
3
4
5
6
7
8
9
{
"type": "LineString",
"coordinates": [
[102.0, 0.0],
[103.0, 1.0],
[104.0, 0.0],
[105.0, 1.0]
]
}

面形状(Polygon)

在coordinates属性中放了一组经纬度坐标存面线上每个点的经纬度

1
2
3
4
5
6
7
8
9
10
11
12
{
"type": "Polygon",
"coordinates": [
[
[100.0, 0.0],
[101.0, 0.0],
[101.0, 1.0],
[100.0, 1.0],
[100.0, 0.0]
]
]
}

注意,coordinates必须形成一个环,也就是第一个坐标必须与最后一个坐标必须相同;
Polygon的coordinates比LineString的coordinates多了一层括号,这是因为面可能由多个环组成,可以想象一下铜钱,它由一个外圈的圆和内圈的正方形构成;
多个环的Polygon还要注意坐标的顺时针或逆时针顺序,一个环的话就随意了。

图层与样式

mapbox有很多种类型,每种类型的图层又配有对应的样式属性,一个标准的图层json格式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"id": "lightLinelayer",//图层id
"type": "line",//图层类型
"source": "lightSource",//数据源id
"layout": {//样式的布局属性
"line-join": "round",
"line-cap": "round"
},
"paint": {//样式的绘制属性
"line-color": "#00FFFF",
"line-width": 5
}
}

样式的信息散落在布局属性(layout)和绘制属性(paint)中,从人类的思维上,layout和paint并没有明显的区分,例如线宽(line-width)和线端点(line-cap)都是对线型的描述,但却分别落在了paint和layout中,
官方对二者的差异如下解释:

Layout properties appear in the layer’s “layout” object. They are applied early in the rendering process and define how data for that layer is passed to the GPU. Changes to a layout property require an asynchronous “layout” step.
布局属性出现在图层的“layout”对象中。它们在渲染过程的早期应用,并定义该层的数据如何传递给GPU。对布局属性的更改需要一个异步的“布局”过程。
Paint properties are applied later in the rendering process. Paint properties appear in the layer’s”paint” object. Changes to a paint property are cheap and happen synchronously.
绘制属性稍后在呈现过程中应用。绘制属性出现在图层的“paint”对象中。更改绘制属性的性能很高,并且是同步的。

也就是说二者的差异体现在渲染的机制不同,所以,具体每种图层有哪些样式属性,是layout还是paint,需要查阅官方文档

数据和样式的修改

下面对例子作一下扩充,我们看一下如何改变样式和数据

修改样式

map.setLayoutPropertymap.setPaintProperty函数可以设置图层的布局属性和绘制属性,这个例子演示了把点的颜色来回切换:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
let currentColor = "#FF0000"
map.addLayer({
"id": "testLayer",
"source": 'source1',
"type": "circle",
"paint": {
"circle-color": currentColor,
"circle-radius": 20
}
});
//启动一个定时器定期修改颜色
setInterval(function (){
if("#FF0000"==currentColor){
currentColor = "#0000FF"
}else {
currentColor = "#FF0000"
}
//三个参数分别是图层id、属性名、属性值
map.setPaintProperty('testLayer',"circle-color",currentColor)
},1000)

修改数据

map.getSource('sourceId').setData函数可以修改数据源内容,这个例子演示了修改坐标信息使红点水平移动:

1
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
const mySource = {
"type": "geojson",
"data": {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [116.338728, 39.913385]
},
"properties": {
"name": "点1",
}
}
]
}
}
map.addSource('source1', mySource)
map.addLayer({
"id": "testLayer",
"source": 'source1',
"type": "circle",
"paint": {
"circle-color": "#FF0000",
"circle-radius": 20
}
});
const xmin = 116.338728, xmax = 116.405419, step = 0.0001
let currentX = xmin;
const source1 = map.getSource('source1');
//启动一个定时器定期修改颜色
setInterval(function () {
currentX += step
if (currentX > xmax) {
currentX = xmin;
}
source1.setData(
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [currentX, 39.913385]
},
"properties": {
"name": "点1",
}
}
]
}
);
}, 10)

这里使用了定时器来刷新坐标,mapbox还支持requestAnimationFrame函数按帧来刷新,使得运动更流畅,可以看这个例子

geojson数据源的缺陷

你一定注意到了本章的标题“添加自定义数据(小数据量的方式)”,为什么要加小数据量这个限制呢?
试想,假如我们有一张数百万条数据的表,把这些数据全转为geojson再丢给mapbox渲染,那对服务端、网络、浏览器都将造成极大的压力。
而且即使电脑性能极佳能够撑住,显示器和人眼的分辨率有限,也无法将这些点分辨出来。

所以、gis专家们提出了分层、切片等解决方法,制定了多种数据源以适应大数据量的展示,在本教程的第四部分会详细涉及。

geojson的方式能够支撑大约一万个点的展示,在第四部分之前,我们依然将以geojson为主进行讲解。


本文采用 CC BY-SA 4.0 协议 ,转载请注明原始链接: https://blog.wowtools.org/2020/12/28/2020-12-28-mapbox-gl-tutorial-3/

×

请作者喝杯咖啡