接上文,之前使用 Cesium.Ion 已经成功将地球效果展示出来了,飞入效果也非常不错。详细可以参考这篇文章:# 拿来就用!Vue3+Cesium 飞入效果封装,3D大屏多场景直接复用
但是仍然存在一个问题没解决, Cesium.Ion 的服务部署在外面,但是我们这边因为众所周知的原因网络受到一些限制。
虽然Cesium的服务是不被禁止访问的,但是访问速度和丢包率也是异常"喜人",所以之前还是打算在这个地方做一下优化。
解决思路
其实想要解决这个问题也非常的简单,将卫星地图(瓦片地图)换成我们自己的服务即可,访问咱们这边的服务是没啥问题的。
目前基本上是两个思路
- 使用在线服务,主要是天地图、腾讯、高德等等几家
- 使用离线服务,自己下载瓦片地图,自己搭建服务
这两种路线我都用了,可以说如果你有资源的话,那么我强烈建议你自己搭建离线地图服务,效果非常好。
最关键的是这套系统就能够实现离线部署了,在某些私有化场景下非常契合。
但是两个问题需要解决,资源和存储空间。
目前资源问题勉强能凑合解决一下,但是存储空间确实没有。毕竟地图下载下来也是真不小,另外目前没有离线部署的需求,所以考虑使用在线服务。
在线服务不推荐腾讯、高德几家,一来配置起来并不好整,我之前尝试腾讯的,鼓捣了半天仅仅弄好了个矢量图,卫星图花了一下午时间也没弄好。
切换到天地图,只用了5分钟就齐活了。
解决方案
使用天地图服务首先去天地图官网注册个账号,地址给大家放一下:www.tianditu.gov.cn/
首先进入控制台,选择开发管理下的开发者认证,认证一下个人开发者。
只有这样才能够创建应用,生成tk。
然后进入开发管理 > 应用管理 > 我的应用 > 创建新应用,简单填写一下必要信息,就能够创建一个新应用了。
复制一下应用密钥(tk)。
实际代码
初始化加载 Cesium图层 的地方设置为 false。
// 初始化 Cesium 地球
const initCesium = async () => {
// 创建 Cesium 视图实例
viewer.value = new Cesium.Viewer('cesiumContainer', {
// 隐藏默认控件,简化界面
timeline: false,
animation: false,
baseLayerPicker: false,
geocoder: false,
homeButton: false,
infoBox: false,
sceneModePicker: false,
navigationHelpButton: false,
// 开启深度检测,避免地形闪烁
scene3DOnly: true,
requestRenderMode: true,
// 不加载默认的 Cesium Ion 影像图层
baseLayer: false
});
// 隐藏 Cesium 版权信息(可选)
viewer.value._cesiumWidget._creditContainer.style.display = 'none';
// 等待 Cesium 完全加载完成
await waitForCesiumFullyLoaded();
// 添加天地图地图影像图层
addTianDituImageryLayer();
// 触发 cesiumReady 事件
emit('cesiumReady', viewer.value);
}
天地图图层主要有两部分,一个是卫星影像底图,另一个是注记图层,当然如果不考虑名称,注记图层可以不添加。
/**
* 添加天地图地图影像图层(卫星图 + 注记)
*/
const addTianDituImageryLayer = () => {
if (!viewer.value) return;
// 使用天地图卫星影像,tk (密钥)
const webKey = '你的tk';
// 天地图卫星影像底图
const imgProvider = new Cesium.WebMapTileServiceImageryProvider({
url: 'https://t{s}.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&FORMAT=tiles&tk=' + webKey,
layer: 'tdtImgBasicLayer',
style: 'default',
format: 'image/jpeg',
tileMatrixSetID: 'GoogleMapsCompatible',
maximumLevel: 18,
minimumLevel: 1,
subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
credit: new Cesium.Credit('天地图'),
// 启用 CORS
enablePickFeatures: false
});
// 添加卫星影像图层
viewer.value.imageryLayers.addImageryProvider(imgProvider);
// 天地图注记图层(地名标注)
const ciaProvider = new Cesium.WebMapTileServiceImageryProvider({
url: 'https://t{s}.tianditu.gov.cn/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&FORMAT=tiles&tk=' + webKey,
layer: 'tdtAnnoLayer',
style: 'default',
format: 'image/jpeg',
tileMatrixSetID: 'GoogleMapsCompatible',
maximumLevel: 18,
minimumLevel: 1,
subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
credit: new Cesium.Credit('天地图注记'),
// 启用 CORS
enablePickFeatures: false
});
// 添加注记图层(叠加在影像之上)
viewer.value.imageryLayers.addImageryProvider(ciaProvider);
console.log('卫星影像加载完成!');
};
这里需要注意:记得将 enablePickFeatures 设为false,避免出现跨域问题。
总结
后续看是否有合适的项目,我会将离线地图的资源和创建方式分享给大家。
如果你的资源足够强,甚至能看到非常精细的卫星图像。
离线地图的玩法也远比在线地图要多得多,你甚至可以DIY某个地方的卫星图像,做出现实版的我的世界。
另外需要注意,天地图的API调用是有限制的,详情可以参考下图。