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(无动画、性能高)。
相关推荐
GIS学姐嘉欣2 天前
Cesium进阶教程(2)线性高度雾
javascript·cesium·gis开发·webgis
GISBox3 天前
一站式体验GISBox 2.1.3:矢量样式扩展与3DTiles位置优化
gis·cesium·倾斜摄影·ifc·osgb·gisbox·切片转换
那年那棵树3 天前
【WebGis】基于WebGis的系统设计与开发
gis·openlayers·cesium·地理信息系统
duansamve3 天前
Cesium中设置背景图片(不是天空盒)
cesium
STCNXPARM7 天前
Linux camera之V4L2子系统详解
android·linux·camera·v4l2架构
地狱为王8 天前
Cesium for Unity叠加行政区划线
unity·gis·cesium
白嫖叫上我9 天前
Cesium切换视角中心点不变
cesium
STCNXPARM9 天前
Android camera之硬件架构
android·硬件架构·camera
STCNXPARM10 天前
Linux camera之Media子系统
linux·camera·v4l2·media子系统