Cesium 实战-最新版(1.104.0)通过异步方式初始化地球,加载影像以及高程图层
- 遇到问题
- 初始化底图
- 初始化高程(监听载入完成事件,开启关闭高程)
- 初始化 3dtile
Cesium 最新版(1.104.0)变动还是挺大的,尤其是涉及图层的渲染加载,差不多是重构级别的变化。
Cesium 1.104.0 开始支持并建议使用异步的方式加载渲染图层。
以下是 官方更新 主要说明:
大意是:为了更好的异步流和图层渲染错误处理,自 1.104.0 开始,readyPromise
模式被弃用,并且从 1.107.0 开始会移除此方法。
因此,为了体验新版功能,最好还是及时更新影像、高程等初始化方法。
受影响的主要是图层相关、地形相关、3dtile 相关,如下:
本文主要介绍一下,新版 cesium(1.104.0)如何加载影像图、高程数据以及 3dtile 数据。
本文包括:遇到问题、初始化底图、初始化高程(监听载入完成事件,切换高程)、初始化 3dtile 四部分。
提示:想快速了解新版如何 加载图层和高程,可以直接跳转至 初始化底图和初始化高程 查看!
遇到问题
看完官方更新之后,想着直接按照官方示例来修改就行,结果也是遇到一些问题。
由于作者使用的是 TMS 资源,因此之前是使用 new Cesium.TileMapServiceImageryProvider()
的方式来加载图层。
但是现在官方建议是使用 Cesium.TileMapServiceImageryProvider.fromUrl
来加载图层。
1. 第一个问题:初始化地图时,不能直接使用 imageryProvider
加载图层。
作者本来以为直接替换就行,结果可想而知:图层不会进行渲染!
原因也比较简单,因为 imageryProvider
需要的是 ImageryProvider
对象,
而 TileMapServiceImageryProvider.fromUrl
创建的是 Promise.<TileMapServiceImageryProvider>
对象,因此图层不会渲染。
2. 第二个问题:跟图层一样,terrainProvider
直接使用 CesiumTerrainProvider.fromUrl
替换也会出问题。
地形高程不会加载,并且地图会变黑!
原因同加载图层,这里不过多解释。
还有个需要注意的地方,如果想做版本(1.104.0之前版本)兼容,terrainProvider
和 terrain
属性只能设置一个,否则会提示错误!
3. 第三个问题:设置开启关闭地形高程问题。
按照以前的方式:
const terrainProvider = viewer.terrainProvider;
// 关闭高程
viewer.terrainProvider = new Cesium.EllipsoidTerrainProvider();
// 开启高程
viewer.terrainProvider = terrainProvider ;
新版环境下,关闭地形比较容易,但是开启有变化,几乎把错都试遍了,比如(以下均不可取,新版方法见下文):
const url = '地形服务地址'
// 创建地形高程对象
const terrain = new Cesium.Terrain(Cesium.CesiumTerrainProvider.fromUrl(url));
const terrainProvider= new Cesium.CesiumTerrainProvider(url));
viewer.terrain = terrainProvider;
viewer.terrain = terrain;
viewer.terrainProvider = terrain;
viewer.terrainProvider = terrain.provider;
初始化底图
Cesium 提供了使用 Promise.<TileMapServiceImageryProvider>
加载图层对象的方法,通过此方法可以直接加载图层。
核心代码(关键是 Cesium.ImageryLayer.fromProviderAsync
):
const url = '图层地址'
const baseLayer = new Cesium.ImageryLayer.fromProviderAsync(Cesium.TileMapServiceImageryProvider.fromUrl(url,{
// 最小级别
minimumLevel: 1,
// 最大级别
maximumLevel: 18,
}))
// 设置监听事件
baseLayer.readyEvent.addEventListener(provider => {
console.log(`已经创建 provider! `);
provider.errorEvent.addEventListener(error => {
console.log(`加载瓦片出错!原因:`, error);
});
});
const viewer = new Cesium.Viewer("cesiumContainer", {
// Use OpenStreetMaps
baseLayer: baseLayer,
// Show Columbus View map with Web Mercator projection
mapProjection: new Cesium.WebMercatorProjection()
});
除此之外,也可以通过设置异步方法(async function
)来创建 imageryProvider
对象,提供给 viewer
进行初始化。
初始化高程(监听载入完成事件,开启关闭高程)
1. 初始化地形高程的方式跟图层比较类似。
核心代码(关键是 new Cesium.Terrain
):
const url = '地形服务地址'
const terrain = new Cesium.Terrain(Cesium.CesiumTerrainProvider.fromUrl(url));
terrain.readyEvent.addEventListener(provider => {
console.log(`已经创建 provider! `);
});
const viewer = new Cesium.Viewer("cesiumContainer", {
// Use Cesium World Terrain
terrain: terrain,
// Show Columbus View map with Web Mercator projection
mapProjection: new Cesium.WebMercatorProjection()
});
2. 关于切换地形高程(开启或关闭地形高程)。
由于地形高程加载改为异步,不能再像以前那样直接替换就行。
作者尝试了多次之后,才偶然想到解决办法,之前也是属于走弯路。
核心代码(关键是 terrain.readyEvent
):
const url = '地形服务地址'
// 创建地形高程对象
const terrain = new Cesium.Terrain(Cesium.CesiumTerrainProvider.fromUrl(url));
// 定义 terrainProvider
let terrainProvider;
// 创建平面地形
const ellipsoidTerrain = new Cesium.EllipsoidTerrainProvider();
// 加载完成之后,记录 terrainProvider 对象
terrain.readyEvent.addEventListener(provider => {
terrainProvider = provider;
});
const viewer = new Cesium.Viewer("cesiumContainer", {
// Use Cesium World Terrain
terrain: terrain,
// Show Columbus View map with Web Mercator projection
mapProjection: new Cesium.WebMercatorProjection()
});
// 分割线 ===================================================================
// 切换地形高程
// 关闭高程
viewer.terrainProvider = ellipsoidProvider;
// 开启高程
viewer.terrainProvider = terrainProvider ;
初始化 3dtile
Cesium 对于 3dtile 加载调整让作者开始有点不适应。
同样,也是异步加载,但是好像没有像图层和高程类那样,提供一个接受者,因此只能使用异步方法(async function
)来创建。
这里需要注意一下,需要用异步方法!
// 使用异步关键字
async function addCesium3DTileset(url,options) {
try {
const tileset = await Cesium.Tileset.fromUrl(url, options);
viewer.scene.primitives.add(tileset);
} catch (error) {
console.log(`Failed to load tileset: ${error}`);
}
}
addCesium3DTileset();