回到背景地图(底图)上来,我们发现,底图上的标注文字大部分都是英文的,这对国内用户很不友好。
本章将介绍一些处理方法,同时本章还涉及到一种常见的数据源/图层:栅格瓦片
方式一 使用mapbox的汉化插件
引入插件
| <script src='https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-language/v0.10.1/mapbox-gl-language.js'></script>
|
新建汉化Control对象,并添加到map中即可:
| 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: { "version": 8, "sources": {}, "layers": [], }, center: [116.405419, 39.923568], zoom: 11 });
const tiandituToken = 'd12deb9576426df9aff82075b754790a';
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;
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的图片:
这些图片就是一个栅格瓦片,多个瓦片拼接完成了背景地图图层的展示。
再回过头来看下天地图的瓦片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;
|
可以看到,url里包含了{z}、{x}、{y}三个参数,事实上,任何瓦片的url都必须包含这三个参数:
z即当前地图的缩放层级。
每个层级上,地球在水平和数值方向上都被切割成了2^z块瓦片,左上角的编号为(0,0),并由左向右递增x、由上往下递增y。
所以,当我们把瓦片url传给mapbox后,mapbox就根据当前地图的层级、经纬度范围,按照这个规则去计算出需要哪些zxy对应的瓦片来填充地图,并发送请求去取图片。
瓦片图层有哪些好处呢?
在服务端,我们可以提前把所有zxy对应的瓦片都预先生成好并存起来(这个过程称为预切片),这样在运行过程中服务端就几乎没什么计算压力了。
而客户端也只需加载视野范围内的瓦片,不用像geojson那样把所有数据都加载过来,压力也少了很多。
有同学要问了,那服务端传过来的是图片,我们没办法修改它的颜色等样式了呀,是的,所以mapbox又制定了矢量瓦片标准,瓦片里不再是一张jpg,而是压缩过的feature,
这样又可以在前端改样式了,矢量瓦片需要涉及一些服务端的知识,我们将在第四部分中详解。
**TIPS:**高德、百度等地图产商也提供了栅格瓦片或矢量瓦片,如有需要,我们也可以把天地图的瓦片换成高德或百度等。
但是,按照高德、百度的用户协议,直接调用瓦片是不合规的;而且为了保密,这些瓦片还经过了一些偏移处理,我们需要一些纠偏手段把偏移去掉,这也是不合规的。