一、方法核心概述
viewer.camera.flyTo 是 Cesium 中控制相机从当前位置平滑飞行到目标位置 的核心方法,区别于直接跳转(setView),它会生成连续的动画过渡,是提升交互体验的关键 API。
1. 基础语法
javascript
viewer.camera.flyTo(options);
- 返回值 :
Promise<boolean>- 飞行完成(或取消)时的Promise,true表示成功完成,false表示被中断/取消。 - 核心逻辑:Cesium 会根据起始位置和目标位置,自动计算飞行路径(默认沿地球表面弧线),并通过插值实现平滑动画。
二、核心参数详解(options 对象)
options 是配置飞行行为的核心,以下是所有常用参数的详细说明:
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
destination |
Cartesian3/Rectangle | 是 | - | 飞行目标位置,支持两种格式: 1. Cartesian3:指定三维坐标(经纬度转笛卡尔坐标) 2. Rectangle:指定矩形区域(自动适配视角覆盖整个区域) |
orientation |
Object | 否 | 自动计算 | 相机到达目标后的朝向,包含 heading/pitch/roll(弧度) |
duration |
Number | 否 | 自动计算(1~5秒) | 飞行总时长(秒),值越小速度越快 |
easingFunction |
EasingFunction | 否 | EasingFunction.LINEAR | 缓动函数,控制飞行速度变化曲线 |
complete |
Function | 否 | - | 飞行完成后的回调函数 |
cancel |
Function | 否 | - | 飞行被取消/中断时的回调 |
endTransform |
Matrix4 | 否 | Transforms.IDENTITY | 相机的参考坐标系(高级用法) |
maximumHeight |
Number | 否 | - | 飞行过程中的最大高度限制 |
pitchAdjustHeight |
Number | 否 | - | 当相机高度低于该值时,自动调整俯仰角避免穿透地形 |
flyOverLongitude |
Number | 否 | - | 强制飞行路径经过指定经度(控制飞行弧线) |
关键参数深度解析
1. destination(目标位置)
这是唯一必填参数,支持两种核心格式:
格式1:Cartesian3 三维坐标(指定经纬度+高度)
最常用的方式,通过 Cesium.Cartesian3.fromDegrees 转换经纬度:
javascript
// 飞向北京(经度116.40,纬度39.90,高度10000米)
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(116.40, 39.90, 10000),
});
- 拓展:也可通过弧度转换
Cartesian3.fromRadians(lngRad, latRad, height)。
格式2:Rectangle 矩形区域(适配视角覆盖区域)
适合"查看某个范围"的场景(如省、市边界),Cesium 会自动计算合适的高度和视角:
javascript
// 飞向中国华东地区(覆盖指定经纬度范围)
const rect = Cesium.Rectangle.fromDegrees(114.0, 27.0, 122.0, 35.0);
viewer.camera.flyTo({
destination: rect,
});
2. orientation(相机朝向)
控制相机到达目标后的"姿态",包含三个核心属性(单位均为弧度):
heading:航向角 - 绕垂直轴(UP)旋转,0=正北,90°=正东,180°=正南(需用Cesium.Math.toRadians转弧度)。pitch:俯仰角 - 绕水平轴(EAST)旋转,0=水平看向地面,-90°=垂直向下,90°=垂直向上。roll:翻滚角 - 绕视线轴旋转,默认0(几乎不用修改)。
javascript
// 飞向上海,指定相机朝向(朝东偏北20°,向下30°俯视)
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(121.47, 31.23, 8000),
orientation: {
heading: Cesium.Math.toRadians(20), // 20°东偏北
pitch: Cesium.Math.toRadians(-30), // 向下30°
roll: 0
}
});
3. easingFunction(缓动函数)
控制飞行速度的变化曲线,Cesium 内置了多种缓动函数,常用的有:
Cesium.EasingFunction.LINEAR:匀速飞行(默认)。Cesium.EasingFunction.QUADRATIC_IN:先慢后快。Cesium.EasingFunction.QUADRATIC_OUT:先快后慢(最常用,过渡更自然)。Cesium.EasingFunction.QUADRATIC_IN_OUT:先慢→快→慢。
javascript
// 缓动函数示例:先快后慢飞向广州
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(113.27, 23.13, 6000),
duration: 4, // 飞行4秒
easingFunction: Cesium.EasingFunction.QUADRATIC_OUT
});
三、完整示例(覆盖核心场景)
示例1:基础飞行(指定经纬度+高度)
javascript
// 初始化Cesium(替换为你的Token)
Cesium.Ion.defaultAccessToken = "你的Cesium Token";
const viewer = new Cesium.Viewer("cesiumContainer");
// 核心:飞向纽约(经度-74.00,纬度40.71,高度12000米)
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(-74.00, 40.71, 12000),
orientation: {
heading: Cesium.Math.toRadians(0), // 朝向正北
pitch: Cesium.Math.toRadians(-45), // 向下45°俯视
roll: 0
},
duration: 3, // 飞行3秒
complete: () => {
console.log("飞行完成,已到达纽约上空");
},
cancel: () => {
console.log("飞行被取消");
}
});
示例2:飞向矩形区域(适配视角覆盖长三角)
javascript
// 定义长三角矩形范围(经纬度)
const yangtzeDelta = Cesium.Rectangle.fromDegrees(
118.0, // 西
29.0, // 南
122.0, // 东
32.0 // 北
);
// 飞向该区域,自动适配高度和视角
viewer.camera.flyTo({
destination: yangtzeDelta,
duration: 5,
easingFunction: Cesium.EasingFunction.CUBIC_IN_OUT // 三次方缓动,更丝滑
});
示例3:结合Promise处理飞行状态
flyTo 返回Promise,可通过 async/await 优雅处理:
javascript
async function flyToParis() {
try {
// 执行飞行
const success = await viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(2.35, 48.86, 10000),
duration: 4
});
if (success) {
console.log("成功到达巴黎!");
// 飞行完成后执行后续操作(如添加标记)
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(2.35, 48.86, 0),
point: {
pixelSize: 10,
color: Cesium.Color.RED
},
label: {
text: "巴黎",
font: "20px Microsoft YaHei",
fillColor: Cesium.Color.WHITE
}
});
}
} catch (e) {
console.error("飞行失败:", e);
}
}
// 调用函数
flyToParis();
四、常见问题与解决方案
问题1:飞行过程中相机穿透地形/模型
原因 :默认开启碰撞检测,但部分场景下计算不准确。
解决方案:
javascript
// 方案1:禁用碰撞检测(允许相机穿过地形)
viewer.scene.screenSpaceCameraController.enableCollisionDetection = false;
// 方案2:设置最大高度/俯仰角限制
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(116.40, 39.90, 5000),
maximumHeight: 5000, // 飞行过程中最高不超过5000米
pitchAdjustHeight: 1000, // 高度低于1000米时自动调整俯仰角
});
问题2:飞行速度过快/过慢
解决方案:
- 显式设置
duration(建议2~5秒,体验最佳)。 - 配合缓动函数(如
QUADRATIC_OUT)让速度过渡更自然。
问题3:多次调用flyTo导致动画冲突
原因 :前一次飞行未完成,后一次调用会中断前一次。
解决方案:飞行前先取消当前未完成的动画:
javascript
// 封装安全的flyTo函数
function safeFlyTo(options) {
// 取消当前正在进行的相机动画
viewer.camera.cancelFlight();
// 执行新的飞行
return viewer.camera.flyTo(options);
}
// 使用
safeFlyTo({
destination: Cesium.Cartesian3.fromDegrees(116.40, 39.90, 8000)
});
问题4:目标位置坐标错误(经纬度顺序搞反)
注意 :Cartesian3.fromDegrees 的参数顺序是 经度(lng)→ 纬度(lat)→ 高度,而非日常的"纬度在前",这是新手最容易犯的错误!
五、高级技巧
1. 自定义飞行路径
通过 flyOverLongitude 强制飞行路径经过指定经度,适合控制"绕地球飞行"的弧线:
javascript
// 从北京飞向洛杉矶,强制经过东经180°(太平洋)
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(-118.24, 34.05, 15000),
flyOverLongitude: Cesium.Math.toRadians(180), // 强制经过180°经度
duration: 10
});
2. 飞行完成后自动旋转视角
javascript
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(121.47, 31.23, 8000),
complete: () => {
// 飞行完成后,每帧旋转0.01弧度(自动环视)
const rotateInterval = setInterval(() => {
viewer.camera.rotateRight(0.01);
// 5秒后停止旋转
setTimeout(() => clearInterval(rotateInterval), 5000);
}, 16); // 约60帧/秒
}
});
六、与 setView 的区别(选型参考)
| 特性 | flyTo | setView |
|---|---|---|
| 动画效果 | 平滑飞行过渡 | 瞬间跳转(无动画) |
| 返回值 | Promise | 无 |
| 适用场景 | 交互操作(如点击按钮飞向目标) | 初始化视角、快速定位 |
| 性能 | 略低(需计算动画) | 更高(直接设置) |
总结
viewer.camera.flyTo是 Cesium 中实现相机平滑飞行的核心方法,必填参数仅destination,支持笛卡尔坐标或矩形区域两种格式。orientation控制相机朝向,需注意heading/pitch/roll均为弧度单位 ,可通过Cesium.Math.toRadians转换角度。- 进阶优化:使用缓动函数(如
QUADRATIC_OUT)提升动画体验,通过cancelFlight避免多次调用冲突,禁用碰撞检测解决地形穿透问题。 - 选型建议:交互场景用
flyTo(有动画),初始化/快速定位用setView(无动画、性能高)。