Cesium 视角切换

Cesium 视角切换 API 详解

下面我将详细讲解 Cesium 中各个视角切换 API 的使用场景、使用方式、参数说明及注意事项,并提供代码示例:

1. viewer.camera.setView(options)

使用场景

  • 地图初始化定位

  • 需要立即切换视角(无动画过渡)

  • 需要精确控制相机位置和方向

使用方式

viewer.camera.setView({
  destination: Cesium.Cartesian3.fromDegrees(116.39, 39.9, 1500),
  orientation: {
    heading: Cesium.Math.toRadians(45),
    pitch: Cesium.Math.toRadians(-30),
    roll: 0.0
  }
});

参数说明

参数类型说明默认值
destinationCartesian3 或 Rectangle目标位置(坐标或矩形区域)必填
orientation.headingnumber偏航角(弧度),0表示正北0
orientation.pitchnumber俯仰角(弧度),-π/2表示垂直向下-π/2
orientation.rollnumber翻滚角(弧度)0
convertboolean是否将方向参数从度数转换为弧度false
endTransformMatrix4变换矩阵undefined
transformMatrix4变换矩阵undefined

注意事项

  1. 此方法会立即切换视角,没有动画效果

  2. 对于经纬度坐标,使用 Cesium.Cartesian3.fromDegrees(lon, lat, height) 进行转换

  3. 角度参数单位为弧度,使用 Cesium.Math.toRadians() 进行转换

  4. 当 destination 是 Rectangle 时,会显示整个矩形区域

2. viewer.camera.flyTo(options)

使用场景

  • 需要动画效果切换视角

  • 场景漫游和路径飞行

  • 用户交互式视角切换

  • 需要控制飞行时间和路径

使用方式

viewer.camera.flyTo({
  destination: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883, 1000),
  orientation: {
    heading: Cesium.Math.toRadians(90),
    pitch: Cesium.Math.toRadians(-25),
    roll: 0
  },
  duration: 8,
  complete: () => console.log("飞行完成!"),
  maximumHeight: 5000,
  pitchAdjustHeight: 50
});

参数说明

参数类型说明默认值
destinationCartesian3 或 Rectangle目标位置必填
orientationObject包含 heading, pitch, roll当前视角
durationnumber飞行时间(秒)自动计算
completefunction完成回调函数undefined
cancelfunction取消回调函数undefined
maximumHeightnumber飞行过程中的最大高度50000000
pitchAdjustHeightnumber避免穿地的高度调整0
flyOverLongitudenumber飞越经度undefined
flyOverLongitudeWeightnumber飞越经度权重undefined
easingFunctionfunction缓动函数EasingFunction.LINEAR_NONE
offsetHeadingPitchRange偏移量undefined

注意事项

  1. 连续调用 flyTo() 可能导致动画中断,使用 complete 回调确保顺序执行

  2. 设置 maximumHeight 可避免飞行高度过高

  3. pitchAdjustHeight 可防止相机穿入地形

  4. 飞行时间(duration)在移动端应适当缩短(3-5秒)

  5. 使用 easingFunction 可创建更自然的飞行效果

3. viewer.zoomTo(target)

使用场景

  • 快速缩放到特定实体

  • 定位点、线、面等几何体

  • 定位模型或3D图块

  • 不需要飞行动画的场景

使用方式

// 创建实体
const entity = viewer.entities.add({
  position: Cesium.Cartesian3.fromDegrees(139.77, 35.68, 100),
  point: { 
    pixelSize: 20, 
    color: Cesium.Color.RED 
  }
});

// 缩放到实体
viewer.zoomTo(entity);

// 缩放到数据源
const dataSource = await Cesium.GeoJsonDataSource.load('data.geojson');
viewer.dataSources.add(dataSource);
viewer.zoomTo(dataSource);

参数说明

参数类型说明
targetEntity/EntityCollection/DataSource要缩放的目标
offsetHeadingPitchRange偏移量(可选)

注意事项

  1. 可以缩放单个实体或整个数据源

  2. 此方法会立即切换视角,没有动画效果

  3. 对于大量实体,建议使用数据源而非遍历实体

  4. 使用 offset 参数可以控制观察角度和距离

  5. 当实体在地形下方时,相机可能会调整到地表上方

4. viewer.flyTo(target, options)

使用场景

  • 需要动画飞行到实体

  • 模型展示和三维可视化

  • 需要控制观察角度和距离

  • 用户交互式聚焦实体

使用方式

// 飞行到实体
viewer.flyTo(entity, {
  offset: new Cesium.HeadingPitchRange(
    Cesium.Math.toRadians(45), 
    Cesium.Math.toRadians(-30), 
    500
  ),
  duration: 4,
  maximumHeight: 3000
});

// 飞行到数据源
viewer.flyTo(dataSource, {
  duration: 6,
  offset: new Cesium.HeadingPitchRange(
    Cesium.Math.toRadians(0),
    Cesium.Math.toRadians(-45),
    1000
  )
});

参数说明

参数类型说明默认值
targetEntity/EntityCollection/DataSource目标实体必填
options.durationnumber飞行时间(秒)自动计算
options.offsetHeadingPitchRange观察偏移量自动计算
options.completefunction完成回调undefined
options.cancelfunction取消回调undefined
options.maximumHeightnumber最大飞行高度50000000
options.pitchAdjustHeightnumber避免穿地高度0
options.easingFunctionfunction缓动函数EasingFunction.LINEAR_NONE

注意事项

  1. 这是定位实体的首选方法(相比 zoomTo)

  2. 使用 offset 参数可以精确控制观察角度

  3. HeadingPitchRange 的三个参数:heading(偏航角)、pitch(俯仰角)、range(距离)

  4. 对于模型展示,推荐俯仰角设置为 -30° 到 -45°

  5. 开启地形时,相机会自动贴合地表

5. 相机方向控制 (Heading/Pitch/Roll)

使用场景

  • 调整相机观察角度

  • 创建特定视角的截图

  • 模拟不同观察方向

  • 配合其他视角切换方法使用

使用方式

// 设置偏航角(0=北,90=东)
viewer.camera.setHeading(Cesium.Math.toRadians(45));

// 设置俯仰角(0=水平,-90=垂直向下)
viewer.camera.setPitch(Cesium.Math.toRadians(-30));

// 设置翻滚角(通常保持0)
viewer.camera.setRoll(0);

// 旋转相机(绕Z轴旋转)
viewer.camera.rotate(Cesium.Cartesian3.UNIT_Z, Cesium.Math.toRadians(-10));

// 俯仰相机(绕X轴旋转)
viewer.camera.rotate(Cesium.Cartesian3.UNIT_X, Cesium.Math.toRadians(-5));

// 获取当前方向
const heading = viewer.camera.heading;
const pitch = viewer.camera.pitch;
const roll = viewer.camera.roll;

参数说明

方法参数说明
setHeading(angle)number设置偏航角(弧度)
setPitch(angle)number设置俯仰角(弧度)
setRoll(angle)number设置翻滚角(弧度)
rotate(axis, angle)axis: Cartesian3, angle: number绕指定轴旋转相机
lookUp(angle)number向上看(增加俯仰角)
lookDown(angle)number向下看(减少俯仰角)
lookLeft(angle)number向左看(增加偏航角)
lookRight(angle)number向右看(减少偏航角)

注意事项

  1. 所有角度参数都是弧度制

  2. 旋转操作是相对于当前相机位置的

  3. 直接设置方向会立即生效(无动画)

  4. 使用 rotate 方法可实现相对旋转

  5. 俯仰角范围通常为 -90°(垂直向下)到 90°(垂直向上)

6. 沿路径飞行

使用场景

  • 场景漫游和导览

  • 飞行模拟

  • 动态展示路径

  • 创建视频飞行路径

使用方式

// 定义路径点
const positions = [
  Cesium.Cartesian3.fromDegrees(116.39, 39.9, 1000), // 北京
  Cesium.Cartesian3.fromDegrees(121.47, 31.23, 2000), // 上海
  Cesium.Cartesian3.fromDegrees(114.05, 22.55, 1500)  // 香港
];

// 创建飞行路径
const flightPath = viewer.entities.add({
  polyline: {
    positions: positions,
    width: 5,
    material: Cesium.Color.YELLOW
  }
});

// 沿路径飞行
viewer.camera.flyTo({
  destination: positions[1],
  orientation: {
    direction: new Cesium.Cartesian3(0, 1, 0), // 自定义方向
    up: Cesium.Cartesian3.UNIT_Z
  },
  flightPath: {
    leadTime: 10, // 向前预测时间
    curve: Cesium.ArcType.GEODESIC // 路径类型
  },
  duration: 20
});

关键参数

参数说明
flightPath.leadTime相机沿飞行路径提前的时间(秒)
flightPath.curve路径曲线类型(GEODESIC, RHUMB, NONE)
orientation.direction自定义相机方向向量
orientation.up自定义相机的上方向
duration飞行总时间

注意事项

  1. 使用 Cesium.SampledPositionProperty 可实现更精确的路径控制

  2. 设置 leadTime 可以使相机朝飞行方向前看

  3. 对于长距离飞行,使用 GEODESIC 曲线类型

  4. 可通过 viewer.camera.moveStartviewer.camera.moveEnd 事件控制飞行过程

  5. 使用 viewer.camera.cancelFlight() 可取消当前飞行

7. 相机范围限制

使用场景

  • 防止相机飞出地球

  • 限制最小/最大高度

  • 约束地图浏览范围

  • 防止相机穿入地下

使用方式

// 限制相机高度范围
viewer.scene.screenSpaceCameraController.minimumZoomDistance = 1000; // 最小高度1000米
viewer.scene.screenSpaceCameraController.maximumZoomDistance = 10000000; // 最大高度

// 限制俯仰角范围
viewer.scene.screenSpaceCameraController.minimumPitch = Cesium.Math.toRadians(-90);
viewer.scene.screenSpaceCameraController.maximumPitch = Cesium.Math.toRadians(0);

// 禁用某些相机操作
viewer.scene.screenSpaceCameraController.enableRotate = false; // 禁用旋转
viewer.scene.screenSpaceCameraController.enableTilt = false; // 禁用倾斜
viewer.scene.screenSpaceCameraController.enableZoom = false; // 禁用缩放

// 设置约束矩形
viewer.scene.camera.constrainedAxis = Cesium.Cartesian3.UNIT_Z; // 约束Z轴
viewer.scene.camera.maximumZoomFactor = 2; // 最大缩放因子

常用约束属性

属性说明
minimumZoomDistance最小缩放距离(米)
maximumZoomDistance最大缩放距离(米)
minimumPitch最小俯仰角(弧度)
maximumPitch最大俯仰角(弧度)
enableRotate是否允许旋转
enableTilt是否允许倾斜
enableZoom是否允许缩放
enableTranslate是否允许平移
constrainedAxis约束的轴
maximumZoomFactor最大缩放因子

注意事项

  1. 开启地形时,高度约束是相对于地形的

  2. 俯仰角约束对于创建特定应用场景很有用

  3. 禁用某些控制器可以创建专用地图浏览体验

  4. 约束矩形对于特定区域的地图应用非常有用

  5. 使用 viewer.scene.screenSpaceCameraController 控制用户交互行为

8. viewer.trackedEntity (实体跟随)

使用场景

  • 跟踪移动的实体(如车辆、飞机、船舶等)

  • 实时监控特定对象

  • 创建第一人称或第三人称视角

  • 动态演示和模拟

使用方式

// 创建实体
const entity = viewer.entities.add({
  position: Cesium.Cartesian3.fromDegrees(0, 0, 0),
  model: {
    uri: 'path/to/model.gltf'
  }
});

// 开始跟踪实体
viewer.trackedEntity = entity;

// 停止跟踪
viewer.trackedEntity = undefined;

// 设置跟踪时的偏移量
entity.viewFrom = new Cesium.Cartesian3(-50.0, 0.0, 50.0); // 在实体的左后方50米,上方50米

参数说明

参数类型说明
trackedEntityEntity要跟踪的实体,设置为undefined停止跟踪

高级配置

// 自定义跟踪视角
viewer.trackedEntity = entity;

// 获取或设置跟踪偏移量
const offset = new Cesium.HeadingPitchRange(
  Cesium.Math.toRadians(45), // 偏航角
  Cesium.Math.toRadians(-30), // 俯仰角
  100.0 // 距离
);

// 使用自定义偏移量
viewer.trackedEntityView = offset;

// 或者直接设置实体的viewFrom属性
entity.viewFrom = new Cesium.Cartesian3(-50.0, 0.0, 50.0);

注意事项

  1. 跟踪实体时,相机会自动保持实体在视野中心,并随实体移动而移动

  2. 可以通过调整 viewer.trackedEntity 来切换跟踪的实体或停止跟踪

  3. 跟踪状态下,用户无法手动控制相机(除非停止跟踪)

  4. 可以通过 viewer.clock.onTick 事件更新实体位置,相机会自动跟随

  5. 跟踪时,相机默认保持一定的距离和角度,可以通过修改实体的 viewFrom 属性来调整

  6. 对于移动的实体,跟踪效果非常流畅,适合车辆监控等场景

9. viewer.camera.viewBoundingSphere(boundingSphere, offset)

使用场景

  • 将相机视角调整到包含一个包围球(BoundingSphere)的视图

  • 用于查看整个3D模型或瓦片集的范围

  • 立即调整视角(无动画)

使用方式

// 获取实体的包围球
const boundingSphere = entity.boundingSphere;

// 调整相机视角到包围球
viewer.camera.viewBoundingSphere(boundingSphere, new Cesium.HeadingPitchRange(0, -0.5, 0));

// 对于瓦片集(Cesium3DTileset)
tileset.readyPromise.then(function(tileset) {
  const boundingSphere = tileset.boundingSphere;
  viewer.camera.viewBoundingSphere(boundingSphere, new Cesium.HeadingPitchRange(0, -0.5, 0));
});

// 手动创建包围球
const center = Cesium.Cartesian3.fromDegrees(116.39, 39.9, 0);
const radius = 1000; // 半径(米)
const boundingSphere = new Cesium.BoundingSphere(center, radius);
viewer.camera.viewBoundingSphere(boundingSphere);

参数说明

参数类型说明
boundingSphereBoundingSphere包围球,包含中心点和半径
offsetHeadingPitchRange可选,观察的偏移量(航向角、俯仰角、距离)

注意事项

  1. 此方法会立即调整相机视角,没有动画

  2. 包围球可以通过实体的 boundingSphere 属性获取,但注意实体必须已加载

  3. 对于瓦片集,需要在 readyPromise 解析后才能获取正确的包围球

  4. 使用偏移量可以调整观察角度和距离

  5. 如果包围球无效或未定义,可能会抛出错误

  6. 此方法适用于需要立即查看整个对象范围的场景

10. viewer.camera.flyToBoundingSphere(boundingSphere, options)

使用场景

  • 动画飞行到包围球的范围

  • 用于平滑过渡到3D模型或瓦片集的全览视图

  • 提供更好的用户体验,避免视角突然跳跃

使用方式

// 获取实体的包围球
const boundingSphere = entity.boundingSphere;

// 飞行到包围球
viewer.camera.flyToBoundingSphere(boundingSphere, {
  duration: 3,
  offset: new Cesium.HeadingPitchRange(0, -0.5, 0)
});

// 对于瓦片集
tileset.readyPromise.then(function(tileset) {
  const boundingSphere = tileset.boundingSphere;
  viewer.camera.flyToBoundingSphere(boundingSphere, {
    duration: 4,
    offset: new Cesium.HeadingPitchRange(0, -0.5, 0)
  });
});

// 手动创建包围球并飞行
const center = Cesium.Cartesian3.fromDegrees(116.39, 39.9, 0);
const radius = 1000;
const boundingSphere = new Cesium.BoundingSphere(center, radius);
viewer.camera.flyToBoundingSphere(boundingSphere, {
  duration: 3,
  offset: new Cesium.HeadingPitchRange(
    Cesium.Math.toRadians(45),
    Cesium.Math.toRadians(-30),
    0
  )
});

参数说明

参数类型说明默认值
boundingSphereBoundingSphere包围球必填
options.durationnumber飞行时间(秒)自动计算
options.offsetHeadingPitchRange观察偏移量自动计算
options.completefunction完成回调函数undefined
options.cancelfunction取消回调函数undefined
options.maximumHeightnumber最大飞行高度自动计算
options.pitchAdjustHeightnumber避免穿地高度0
options.easingFunctionfunction缓动函数EasingFunction.LINEAR_NONE

注意事项

  1. 此方法会动画飞行到包围球,提供平滑的过渡效果

  2. 包围球可以通过实体的 boundingSphere 属性获取,但注意实体必须已加载

  3. 对于瓦片集,需要在 readyPromise 解析后才能获取正确的包围球

  4. 使用偏移量可以调整观察角度和距离

  5. 飞行时间(duration)和最大高度(maximumHeight)可以控制飞行的速度和高度

  6. 如果包围球无效或未定义,可能会抛出错误

  7. 此方法特别适合展示大型3D模型或建筑群

11. 综合示例:实体跟踪与包围球结合使用

javascript

// 创建移动实体(如车辆)
const vehicle = viewer.entities.add({
  position: Cesium.Cartesian3.fromDegrees(116.39, 39.9, 0),
  model: {
    uri: 'models/vehicle.gltf',
    scale: 1.0
  },
  orientation: new Cesium.VelocityOrientationProperty(position) // 根据速度方向自动旋转
});

// 设置跟踪偏移量(第三人称视角)
vehicle.viewFrom = new Cesium.Cartesian3(-20.0, -10.0, 15.0);

// 开始跟踪
viewer.trackedEntity = vehicle;

// 模拟车辆移动
let longitude = 116.39;
setInterval(() => {
  longitude += 0.001; // 向东移动
  vehicle.position = Cesium.Cartesian3.fromDegrees(longitude, 39.9, 0);
}, 100);

// 飞行到车辆的全览视图
document.getElementById('overview-btn').addEventListener('click', function() {
  // 暂停跟踪
  const wasTracking = viewer.trackedEntity;
  viewer.trackedEntity = undefined;
  
  // 飞行到包围球
  viewer.camera.flyToBoundingSphere(vehicle.boundingSphere, {
    duration: 2,
    offset: new Cesium.HeadingPitchRange(0, -Math.PI/4, vehicle.boundingSphere.radius * 2.5),
    complete: function() {
      // 飞行完成后恢复跟踪
      if (wasTracking) {
        viewer.trackedEntity = vehicle;
      }
    }
  });
});

12. 瓦片集(3D Tile的特殊处理

// 加载3D瓦片集
const tileset = await Cesium.Cesium3DTileset.fromUrl('tilesets/building/tileset.json');
viewer.scene.primitives.add(tileset);

// 等待瓦片集加载完成
tileset.readyPromise.then(function(tileset) {
  // 获取瓦片集的包围球
  const boundingSphere = tileset.boundingSphere;
  
  // 飞行到瓦片集
  viewer.camera.flyToBoundingSphere(boundingSphere, {
    duration: 4,
    offset: new Cesium.HeadingPitchRange(
      Cesium.Math.toRadians(0),   // 正北方向
      Cesium.Math.toRadians(-45), // 45度俯角
      boundingSphere.radius * 1.5 // 距离为半径的1.5倍
    )
  });
  
  // 或者立即查看瓦片集
  // viewer.camera.viewBoundingSphere(boundingSphere);
});

// 处理瓦片集的可见性
tileset.style = new Cesium.Cesium3DTileStyle({
  color: {
    conditions: [
      ["${Height} >= 300", "rgba(45, 0, 75, 0.5)"],
      ["${Height} >= 200", "rgb(102, 71, 151)"],
      ["${Height} >= 100", "rgb(170, 162, 204)"],
      ["${Height} >= 50", "rgb(224, 226, 238)"],
      ["${Height} >= 25", "rgb(252, 230, 200)"],
      ["${Height} >= 10", "rgb(248, 176, 87)"],
      ["${Height} >= 5", "rgb(198, 106, 11)"],
      ["true", "rgb(127, 59, 8)"]
    ]
  }
});

13. 注意事项与最佳实践

  1. 性能考虑

    • 对于大型瓦片集,使用 flyToBoundingSphere 而不是 viewBoundingSphere 可以提供更好的用户体验

    • 在移动设备上,减少飞行时间和复杂度

  2. 错误处理

    javascript

  • try {
      viewer.camera.viewBoundingSphere(boundingSphere);
    } catch (e) {
      console.error("无法查看包围球:", e);
      // 回退到默认视角
      viewer.camera.setView({
        destination: Cesium.Cartesian3.fromDegrees(116.39, 39.9, 10000)
      });
    }
  • 内存管理

    • 当不再需要跟踪实体时,及时设置 viewer.trackedEntity = undefined

    • 对于大型瓦片集,使用适当的细节层次(LOD)设置

  • 用户体验

    • 提供视觉反馈,如加载指示器

    • 允许用户取消飞行操作

    • 提供返回上一视图的功能

  • 移动端适配

    // 检测移动设备
    const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
    
    // 调整飞行参数
    viewer.camera.flyToBoundingSphere(boundingSphere, {
      duration: isMobile ? 2 : 4, // 移动端飞行时间更短
      maximumHeight: isMobile ? 5000 : 10000 // 移动端最大高度更低
    });

通用注意事项

  1. 坐标系转换

    • 使用 Cesium.Cartesian3.fromDegrees(lon, lat, height) 转换经纬度为三维坐标

    • 使用 Cesium.Cartographic.fromCartesian(cartesian) 转换三维坐标为经纬度

  2. 性能优化

    • 飞行到大量实体时,优先使用 viewer.flyTo(DataSource)

    • 复杂场景中设置 flyTo 的 maximumHeight 避免俯冲穿模

    • 避免频繁调用视角切换方法

  3. 地形交互

    • 开启地形时 (viewer.terrainProvider = Cesium.createWorldTerrain())

    • 相机高度会自动调整到地形上方

    • 使用 pitchAdjustHeight 调整避免穿地

  4. 移动端适配

    • 减少飞行时间(duration: 3)

    • 简化路径和动画

    • 禁用不必要的相机操作

  5. 动画冲突处理

    javascript

  1. viewer.camera.flyTo({
      // 参数...
      complete: () => {
        // 第一个飞行完成后执行第二个飞行
        viewer.camera.flyTo({
          // 第二个飞行参数...
        });
      }
    });
  2. 方向参数参考

    • Heading:0 表示正北,π/2 为正东(弧度制)

    • Pitch:0 表示水平,-π/2 表示垂直向下

    • Roll:0 表示水平,通常不需要调整

这些API和方法提供了Cesium中视角切换的全面控制,根据具体场景选择合适的方法和参数组合,可以创建出流畅、自然的3D场景导航体验。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值