飞行漫游,就是让Camera
飞行。Camera
有一些方法可以实现位置、视角的调整,比如flyTo
,setView
方法。但这些方法并不能沿着我们想要的路径调整,在通过插值的方法不停的调用setView
,但这样会造成视图卡顿,而且计算起来也很麻烦。所以我们最好是借助entity
,通过跟踪运动中的entity
就可以实现Camera
的飞行了。官网例子
效果图
当然,实际效果要比gif更流畅
设置路径
我们直接修改官网的CZML
文件,把没用的东西统统删掉。
- 替换成自己的路径。注意时间(
interval
)和时间快进倍数(multiplier
)的关系
cartographicDegrees
中,每一行的参数分别是时间点、经度、纬度、高程。
我设置了18个点,选择三分钟除以10倍,也就是18秒跑完一圈 - 隐藏路径,把
width
设为0 - 隐藏飞机,把
billboard
删掉
[
{
"id": "document",
"name": "CZML Path",
"version": "1.0",
"clock": {
"interval": "2020-08-04T10:00:00Z/2020-08-04T10:03:00Z",
"currentTime": "2020-08-04T10:00:00Z",
"multiplier": 10
}
},
{
"id": "path",
"name": "path with GPS flight data",
"path": {
"width": 0,
"leadTime": 10,
"trailTime": 1000,
"resolution": 5
},
"position": {
"epoch": "2020-08-04T10:00:00Z",
"cartographicDegrees": [
0, 120.184679, 30.250211, 176,
10, 120.184507, 30.252099, 173,
20, 120.185151, 30.253816, 172,
30, 120.185795, 30.254631, 170,
40, 120.187125, 30.255704, 170,
50, 120.189099, 30.255704, 167,
60, 120.19176, 30.255103, 171,
70, 120.194249, 30.254331, 165,
80, 120.195236, 30.252442, 170,
90, 120.195365, 30.250211, 154,
100, 120.19455, 30.247808, 132,
110, 120.192575, 30.24579, 127,
120, 120.189614, 30.244761, 117,
130, 120.187297, 30.244803, 113,
140, 120.185795, 30.24549, 103,
150, 120.183864, 30.247035, 103,
160, 120.183907, 30.248795, 107,
170, 120.183679, 30.249211, 176,
180, 120.184679, 30.250211, 176
]
}
}
]
飞行漫游
我把上面的czml
保存成了json
格式(它就是json
!)并加载。
这里用到了插值,作用是在你拐弯的时候一样如丝般润滑
viewer.dataSources.add(Cesium.CzmlDataSource.load('./path.json')).then((ds) => {
flyEntity = ds.entities.getById('path')
flyEntity.position.setInterpolationOptions({
interpolationDegree: 5,
interpolationAlgorithm: Cesium.LagrangePolynomialApproximation
})
viewer.trackedEntity = flyEntity
})
调整视角
调整视角,是在viewer.scene.preUpdate.addEventListener(function () {})
中完成的。在这个函数中,调用viewer.camera.lookAt()
方法改变视角。
lookAt
的第二个参数,可以是坐标向量,也可是角度对象。我这里是用了向量(Cartesian3
对象)作为第二个参数。你也可以使用角度对象(HeadingPitchRange
,可以参考 easyCesium 的博客)
我这里是让Camera
每时每刻对准某一点,你可以在其中实现更复杂的操作
const target = new Cesium.Cartesian3.fromDegrees(120.189, 30.254, 300)
function setRoamView() {
if (flyEntity) {
const center = flyEntity.position.getValue(viewer.clock.currentTime)
if (center) {
const vector = new Cesium.Cartesian3(target.x - center.x, target.y - center.y, 300)
viewer.camera.lookAt(center, vector)
}
}
}
viewer.scene.preUpdate.addEventListener(setRoamView)
补充
用户可能会想到停止漫游,两步:
- 取消
Camera
跟踪,即viewer.trackedEntity = null
- 取消事件绑定,
viewer.scene.preUpdate.removeEventListener(setRoamView)