一、FlyTo概述
Cesium是一款基于WebGL开源JavaScript库,用于构建3D地球、地图及其他视觉化场景。它提供了许多常用的地图功能,如场景切换、相机控制、基础地图功能、卫星影像、地形调整、3D建筑物、KML/KMZ支持等等。其中,FlyTo是Cesium中的一个重要组件,负责将相机飞行到指定的位置、方向和高度,具有非常好的视觉效果。
官方文档中对FlyTo的概括如下:
flyTo(destination, options)
destination表示要飞行到的目标位置,可以是一个Entity、Cartographic、Rectangle、BoundingSphere等Cesium内置对象,也可以是一个笛卡尔坐标系下的三维坐标数组。options表示飞行参数,包括飞行时长、视角、朝向、缩放等选项。另外,Cesium还提供了可链式调用的Camera.flyTo()接口,用起来更加简洁方便。
二、使用方法
1、简单飞行
以下代码展示了如何飞到经度为120,纬度为30,高度为1000米的位置:
viewer.camera.flyTo({ destination: Cesium.Cartesian3.fromDegrees(120, 30, 1000) });
上述代码中,我们首先通过Cesium.Cartesian3.fromDegrees()将经纬度转换为笛卡尔坐标系下的三维坐标,然后传入Camera.flyTo()中的desination参数即可完成飞行。Cesium基于惯性滚动和相机动画,实现了相机的平滑过渡并使飞行变得更加自然流畅。
2、定制化飞行
2.1、飞行参数
飞行参数可以控制飞行时长、视角、朝向、缩放等选项,以下是一个完整的范例:
viewer.camera.flyTo({ destination: Cesium.Cartesian3.fromDegrees(120, 30, 5000), orientation: { heading: Cesium.Math.toRadians(-50), pitch: Cesium.Math.toRadians(-20), roll: 0.0 }, duration: 3, complete: function() { console.log('Fly to complete!'); } });
其中,orientation对象用于控制相机的方向,包括heading、pitch、roll三个角度分量,单位为弧度;duration表示飞行时间,单位为秒;complete是一个回调函数,飞行结束后会自动调用该函数。
2.2、多段飞行
我们也可以实现多段飞行,将相机分别飞到多个位置。以下是一个飞行轨迹的范例:
var positions = [ Cesium.Cartesian3.fromDegrees(120, 30, 5000), Cesium.Cartesian3.fromDegrees(122, 32, 5000), Cesium.Cartesian3.fromDegrees(125, 35, 5000), ]; viewer.camera.flyTo({ duration: 3, orientation: { heading: Cesium.Math.toRadians(-50), pitch: Cesium.Math.toRadians(-20), roll: 0.0 }, destination: positions[0], complete: function() { viewer.camera.flyTo({ duration: 3, orientation: { heading: Cesium.Math.toRadians(-50), pitch: Cesium.Math.toRadians(-20), roll: 0.0 }, destination: positions[1], }); } }); viewer.clock.onTick.addEventListener(function() { var distance = Cesium.Cartesian3.distance(viewer.camera.position, positions[1]); if(distance < 10000) { viewer.camera.flyTo({ duration: 3, orientation: { heading: Cesium.Math.toRadians(-50), pitch: Cesium.Math.toRadians(-20), roll: 0.0 }, destination: positions[2], }); } });
以上代码中,我们首先定义了三个目标位置,并使用一次flyTo()将相机飞到第一个位置。并在flyTo()的complete回调函数中,再次调用flyTo()将相机飞到第二个位置。由于Cesium的飞行是基于惯性滚动和相机动画的,我们无法直接判断相机是否到达目标位置。因此,我们需要通过监听Cesium的Clock轨迹事件,计算相机与目标位置之间的距离,并在距离小于阈值时,再次调用flyTo()将相机飞到第三个位置。
三、FlyTo实现原理
FlyTo的实现主要涉及以下两个方面:
1、摄像机运动学
对于3D场景中的相机视角,我们通常使用欧拉角来描述相机的方向。欧拉角包括航向角(Heading)、俯仰角(Pitch)和滚转角(Roll)。Cesium在内部维护了相机的欧拉角、位置、速度等状态信息,并使用时间戳来控制场景的更新。
2、插值和动画
Cesium的FlyTo是通过插值和动画来实现的。具体而言,FlyTo使用了渐进式插值和Cubic Hermite样条插值(CHAI)算法,将用户指定的相机位置和方向与当前相机位置和方向进行插值,瞬间跳跃到一个新的位置和方向。同时,为了避免跃变造成的视觉不适,FlyTo使用了渐进过渡和缓动函数,在一定时间内平滑过渡到新的位置、方向和缩放比例。
四、总结
通过上述分析,我们可以看到,Cesium FlyTo在3D场景中是非常重要且常用的一个组件,其基于惯性滚动和相机动画,实现了相机的平滑过渡并使飞行变得更加自然流畅。同时,FlyTo通过插值和动画,将用户指定的相机位置和方向与当前相机位置和方向进行插值,在一定时间内平滑过渡到新的位置、朝向和缩放比例。这种实现方式,使得相机的运动轨迹更加自然、流畅,同时也对视觉体验产生了积极的影响。