mapbox-gl教程(4):适配国内底图

回到背景地图(底图)上来,我们发现,底图上的标注文字大部分都是英文的,这对国内用户很不友好。
本章将介绍一些处理方法,同时本章还涉及到一种常见的数据源/图层:栅格瓦片

方式一 使用mapbox的汉化插件

引入插件

1
<script src='https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-language/v0.10.1/mapbox-gl-language.js'></script>

新建汉化Control对象,并添加到map中即可:

1
2
3
4
5
6
7
8
9
10
11
12
mapboxgl.accessToken = 'pk.eyJ1IjoiaW1saXV5dSIsImEiOiJjbDM4aHM4eXowMDBpM2RvZGdxdGZjeWMxIn0.mYtay02E_Z4iYOsDx3IdoA';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v9',
center: [116.405419, 39.923568],
zoom: 11
});
mapboxgl.setRTLTextPlugin('https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-rtl-text/v0.1.0/mapbox-gl-rtl-text.js');
var languageControl = new MapboxLanguage({
defaultLanguage: 'zh'//设置语言为中文
});
map.addControl(languageControl);

实际用下来,这种方式效果一般,依然有少量的英文标注,而且由于是国外的数据源,POI的密度也比较低。

方式二 使用国内数据源

国家地理信息公共服务平台“天地图”(以下简称“天地图“)是国家基础地理信息中心建设的网络化地理信息共享与服务门户。
天地图提供的背景地图,国家背景、更新及时、地物详细、完全免费、值得信赖。本小节我们就来学习如何将mapbox的背景地图换成天地图的:

emmm,这下好多了,看下代码:
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
const map = new mapboxgl.Map({
container: 'map',
style: {//为map构造一个空的style
"version": 8,
"sources": {},
"layers": [],
},
center: [116.405419, 39.923568],
zoom: 11
});

//天地图的token
const tiandituToken = 'd12deb9576426df9aff82075b754790a';
/*
* 天地图提供了多种背景地图和标注供选择,
* 只要从http://lbs.tianditu.gov.cn/server/MapService.html找到对应的url即可
* 这里使用了了矢量地图和注记
* */

//矢量底图
const vecwUrl = 'https://t0.tianditu.gov.cn/vec_w/wmts?' +
'SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&' +
'TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=' + tiandituToken;
//矢量注记
const cvawUrl = 'https://t3.tianditu.gov.cn/cva_w/wmts?' +
'SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&' +
'TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=' + tiandituToken;

/**
* 向地图中添加一个栅格瓦片图层
* @param map
* @param url 瓦片url
* @param sourceId 数据源id,保证唯一性即可
* @param layerId 图层id,保证唯一性即可
*/

function addRasterTileLayer(map, url, sourceId, layerId) {
map.addSource(sourceId, {
type: 'raster',
tiles: [url],
tileSize: 256
});
map.addLayer({
id: layerId,
type: 'raster',
source: sourceId
});
}

map.on('load', function () {
//这里选择加载矢量底图及其标注
addRasterTileLayer(map,vecwUrl,'vecw','vecw')
addRasterTileLayer(map,cvawUrl,'cvaw','cvaw')
})

我们先构造了一个空的style,这样map对象里就不含任何数据源和图层,也就是一张空白的地图。
然后我们定义了一个addRasterTileLayer函数,用以构建栅格瓦片数据源和图层并添加到地图中。
最后再用天地图的瓦片url构造了一个背景图层和一个背景标注图层。

栅格瓦片简介

按下F12打开开发者工具,然后滚动几下地图,你会发现mapbox请求了许多256*256的图片:
F12
这些图片就是一个栅格瓦片,多个瓦片拼接完成了背景地图图层的展示。

再回过头来看下天地图的瓦片url

1
2
3
const vecwUrl = 'https://t0.tianditu.gov.cn/vec_w/wmts?' +
'SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&' +
'TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=' + tiandituToken;

可以看到,url里包含了{z}、{x}、{y}三个参数,事实上,任何瓦片的url都必须包含这三个参数:
ZXY

z即当前地图的缩放层级。
每个层级上,地球在水平和数值方向上都被切割成了2^z块瓦片,左上角的编号为(0,0),并由左向右递增x、由上往下递增y。
所以,当我们把瓦片url传给mapbox后,mapbox就根据当前地图的层级、经纬度范围,按照这个规则去计算出需要哪些zxy对应的瓦片来填充地图,并发送请求去取图片。

瓦片图层有哪些好处呢?
在服务端,我们可以提前把所有zxy对应的瓦片都预先生成好并存起来(这个过程称为预切片),这样在运行过程中服务端就几乎没什么计算压力了。
而客户端也只需加载视野范围内的瓦片,不用像geojson那样把所有数据都加载过来,压力也少了很多。

有同学要问了,那服务端传过来的是图片,我们没办法修改它的颜色等样式了呀,是的,所以mapbox又制定了矢量瓦片标准,瓦片里不再是一张jpg,而是压缩过的feature,
这样又可以在前端改样式了,矢量瓦片需要涉及一些服务端的知识,我们将在第四部分中详解。

TIPS:高德、百度等地图产商也提供了栅格瓦片或矢量瓦片,如有需要,我们也可以把天地图的瓦片换成高德或百度等。
但是,按照高德、百度的用户协议,直接调用瓦片是不合规的;而且为了保密,这些瓦片还经过了一些偏移处理,我们需要一些纠偏手段把偏移去掉,这也是不合规的。


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

×

请作者喝杯咖啡