viewer.camera.flyTo 全面教程

一、方法核心概述

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:飞行速度过快/过慢

解决方案

  1. 显式设置 duration(建议2~5秒,体验最佳)。
  2. 配合缓动函数(如 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
适用场景 交互操作(如点击按钮飞向目标) 初始化视角、快速定位
性能 略低(需计算动画) 更高(直接设置)

总结

  1. viewer.camera.flyTo 是 Cesium 中实现相机平滑飞行的核心方法,必填参数仅 destination,支持笛卡尔坐标或矩形区域两种格式。
  2. orientation 控制相机朝向,需注意 heading/pitch/roll 均为弧度单位 ,可通过 Cesium.Math.toRadians 转换角度。
  3. 进阶优化:使用缓动函数(如 QUADRATIC_OUT)提升动画体验,通过 cancelFlight 避免多次调用冲突,禁用碰撞检测解决地形穿透问题。
  4. 选型建议:交互场景用 flyTo(有动画),初始化/快速定位用 setView(无动画、性能高)。
相关推荐
李剑一1 天前
拿来就用!Vue3+Cesium 飞入效果封装,3D大屏多场景直接复用
前端·vue.js·cesium
曲折2 天前
Cesium-气象要素PNG色斑图叠加
前端·cesium
GIS开发特训营15 天前
Cesium Shader 实战:三维 GIS 可视化进阶教程
gis·cesium·gis开发·webgis
GIS学姐嘉欣22 天前
Cesium进阶教程(2)线性高度雾
javascript·cesium·gis开发·webgis
GISBox23 天前
一站式体验GISBox 2.1.3:矢量样式扩展与3DTiles位置优化
gis·cesium·倾斜摄影·ifc·osgb·gisbox·切片转换
那年那棵树23 天前
【WebGis】基于WebGis的系统设计与开发
gis·openlayers·cesium·地理信息系统
duansamve23 天前
Cesium中设置背景图片(不是天空盒)
cesium
STCNXPARM1 个月前
Linux camera之V4L2子系统详解
android·linux·camera·v4l2架构
地狱为王1 个月前
Cesium for Unity叠加行政区划线
unity·gis·cesium