Cesium加载MVT矢量瓦片服务
基于mapbox-vector-tiles-basic-js-renderer的方式,引入mvt-imagery-provider库加载MVT服务。
环境
基于vite创建项目
vite.config.js:
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import cesium from 'vite-plugin-cesium';
import path from 'path';
export default defineConfig({
plugins: [vue(),cesium()],
resolve: {
alias: {
cesium: path.resolve(__dirname, 'node_modules/cesium/Build/Cesium'),
},
},
server: {
port: 3000,
},
});
依赖版本:
"dependencies": {
"@mapbox/vector-tile": "^2.0.3",
"mapbox-gl": "^1.13.3",
"mvt-imagery-provider": "^1.0.3",
"protobufjs": "^7.4.0",
"vue": "^3.4.21"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.0.4",
"cesium": "^1.127.0",
"vite": "^5.4.14",
"vite-plugin-cesium": "^1.2.23"
}
代码
Template
mmmap用于mapboxgl地图展示,C用于Cesium地图展示
<template>
<div id='mmmap'>
</div>
<div id="C">
</div>
</template>
Script setup
引入所需的包
import { onMounted } from 'vue'
import mapboxgl from 'mapbox-gl'
import * as Cesium from 'cesium';
import MVTImageryProvider from 'mvt-imagery-provider';
onMounted:
基础配置
mapboxgl.accessToken ='your-mapboxgl-access-token';
Cesium.Ion.defaultAccessToken = "your-cesium-access-token";
const viewer = new Cesium.Viewer('C');
// 启用抗锯齿
viewer.scene.globe.enableAntialiasing = true;
//调整文本渲染质量
viewer.scene.textureAnisotropy = 16;
根据mvt服务地址获取.json或.mvt文件,获取文件后提取出样式部分:
let response = await fetch('your-mvt-service-address');
let s = null;
if (response.ok) {
s = await response.json();
}
注意这里的s用于后续构造ImageryProvider时作为style参数传入,s可以具有如下的基本格式:
{
"bearing": 0,
"center": [
lat,
lon
],
"glyphs": "your-glyphs-service-address",
"layers": [
{
"id": "id",
"source": "your-style-source",
"source-layer": "your-source-layer",
"type": "symbol",
"layout": {
......
},
"paint": {
...
},
"maxzoom": 1,
"minzoom": 0,
},
......
],
"metadata": {},
"name": "",
"pitch": 0,
"sources": {
"your-style-source": {
"rectangle": [
lat1,
lat2,
lon1,
lon2
],
"tiles": [
"your-tile-service-address"
],
"type": "vector"
}
},
"sprite": "your-sprite-service-address",
"version": 8,
"zoom": 1
}
部分数据处理:
由于mvt-imagery-provider包年久失修,部分内容与新版本框架有冲突,部分冲突如下:
精灵图服务地址:
//mvt-imagery-provider包会根据传入的style参数中的sprite属性构造精灵图服务地址,当前版本会在地址后自动添加@2x表示2级清晰度,所以需要修改精灵图服务地址为如下格式:
s.sprite = "http://your-sprite-service-address/sprite";
//如此修改后最终的请求URL即为http://your-sprite-service-address/sprite@2x
绘制属性冲突:
在图层的绘制属性(paint)中,fill-pattern属性和其他属性冲突导致type为fill的面类型数据不能正常加载,将该属性删除:
for (let lyr of s['layers']){
let {layout, paint} = lyr;
if (paint.hasOwnProperty('fill-pattern')){
delete paint['fill-pattern'];
}
}
布局属性冲突:
在图层的布局属性(layout)中,text-radial-offset径向偏移量属性Cesium无法识别,直接删除。同时text-justify属性可能被设置为auto,而Cesium对于该属性只接受center、left、right三个配置,改为居中即可。
for (let lyr of s['layers']){
if (layout.hasOwnProperty('text-radial-offset')){
delete layout['text-radial-offset'];
}
if (layout.hasOwnProperty('text-justify')){
if (layout['text-justify'] === 'auto'){
layout['text-justify'] = 'center';
}
}
}
图层顺序:
如果部分图层未能看到可能是因为加载顺序的原因,尝试将图层反转:
s.layers.reverse();
构造provider并添加入图层:
const mvtProvider = new MVTImageryProvider({
style: s,
});
viewer.imageryLayers.addImageryProvider(mvtProvider);
图标与文字:
MVT服务所需的文字是通过字形服务获取到的,即"glyphs": “your-glyphs-service-address”,该服务获取到的往往是.pbf文件,Cesium不一定能识别,可能会出现只展示图标而未能展示文字的情况。对此可以将文字部分单独加载,忽略layers中type为symbol的图层,即图标文字图层,将数据源通过Cesium创建独立实体加载:
如果数据源为.gdb文件可通过ArcGIS的要素转JSON工具将其转换为GeoJSON类型数据加载,注意坐标系应选择WGS_1984(WGS84)。
具体添加方法可以看这篇:Cesium加载GeoJson数据添加文字标签