【Cesium系列第三篇】Cesium Camera常用设置方法详解

前言:在前两篇文章中,我们已完成Vue+Vite+TS+Cesium的环境搭建,并创建了基础三维场景,同时详细讲解了Viewer的option配置参数。在Cesium三维场景中,Camera(相机)是控制视角的核心,相当于我们观察场景的“眼睛”——所有场景可视化效果都依赖Camera的视角呈现。本文作为系列第三篇,将聚焦Camera核心内容:先讲解Camera的基本概念与核心属性,再通过具体代码示例演示几种常用的视角设置方法,最后说明不同设置方法的效果差异,帮助大家灵活控制场景视角。

一、Camera基本概念

在Cesium中,Camera是一个虚拟的“相机”对象,用于定义观察三维场景的视角和姿态。我们在场景中看到的所有内容,都是Camera“拍摄”到的画面。理解Camera的核心属性,是灵活控制视角的基础。

1.1 核心属性(视角控制的关键)

Camera的核心属性决定了其位置和观察姿态,主要包括以下4个:

  • position(位置):Camera在三维空间中的具体坐标,默认使用Cesium笛卡尔坐标系(Cartesian3),也可通过经纬度+高度转换得到。这是控制“相机在哪里”的关键。

  • heading(航向角):相机在水平面上的旋转角度,以正北方向为0度,顺时针旋转为正方向(单位:弧度)。控制“相机水平朝向哪个方向”(如朝东、朝南)。

  • pitch(俯仰角):相机在垂直方向的旋转角度,以水平视角为0度,向下旋转为负,向上旋转为正(单位:弧度)。控制“相机是俯视、平视还是仰视”(如俯视地球、平视地平线)。

  • roll(翻滚角):相机绕自身视线方向的旋转角度,0度为水平状态,顺时针为正,逆时针为负(单位:弧度)。一般用于特殊场景(如飞行模拟),常规三维场景中基本设为0。

补充说明:Cesium中角度与弧度的转换需使用 Cesium.Math.toRadians(角度值) 方法,因为Camera的角度属性仅支持弧度单位。例如:将30度转换为弧度 →Cesium.Math.toRadians(30)

1.2 Camera与Viewer的关系

在我们前两篇创建的场景中,Camera是Viewer实例的一个属性,可通过 viewer.camera 直接获取和操作,无需单独创建。例如:


// 初始化Viewer后,直接获取Camera实例
const viewer = new Cesium.Viewer(container, options);
const camera = viewer.camera; // 获取Camera对象

二、Camera常用设置方法(附代码示例)

基于前两篇搭建的Vue+Vite+TS环境,以下所有代码均在CesiumBasicViewer.vue组件中扩展实现。核心设置方法分为4种:setView(立即定位)flyTo(平滑飞行定位)lookAt(指向目标点)手动修改属性,分别适用于不同场景需求。

2.1 方法1:setView(立即定位,无动画)

setView 方法用于将相机“瞬间”定位到目标视角,无平滑过渡动画,适用于需要快速切换视角的场景(如初始化默认视角、快速跳转场景)。

核心参数

  • destination:必选,目标位置,支持两种格式:

    • Cartesian3:经纬度+高度转换后的笛卡尔坐标(常用,定位具体点)

    • Rectangle:矩形范围(定位一片区域,相机会自动调整高度以完整显示区域)

  • orientation:可选,相机姿态(heading+pitch+roll),不设置则使用默认姿态。

代码示例


<script setup lang="ts">
import { onMounted, ref, onUnmounted } from 'vue'
import * as Cesium from 'cesium'

const viewerRef = ref<HTMLDivElement | null>(null)
let viewer: Cesium.Viewer | null = null

onMounted(() => {
  if (!viewerRef.value) return

  // 初始化Viewer(使用前一篇推荐的option参数)
  viewer = new Cesium.Viewer(viewerRef.value, {
    homeButton: true,
    fullscreenButton: true,
    baseLayerPicker: true,
    timeline: false,
    animation: false,
    geocoder: false,
    navigationHelpButton: false,
    sceneModePicker: false,
    scene3DOnly: true,
    requestRenderMode: true,
    maximumRenderTimeChange: 0.01
  })

  // setView方法:立即定位到北京(无动画)
  viewer.camera.setView({
    // 目标位置:北京(经度116.403874,纬度39.914885,高度10000米)
    destination: Cesium.Cartesian3.fromDegrees(116.403874, 39.914885, 10000),
    // 相机姿态:航向角0(正北),俯仰角-30°(俯视),翻滚角0
    orientation: {
      heading: Cesium.Math.toRadians(0),
      pitch: Cesium.Math.toRadians(-30),
      roll: Cesium.Math.toRadians(0)
    }
  })

  // 扩展:定位到矩形区域(如中国东部,自动调整高度)
  // viewer.camera.setView({
  //   destination: Cesium.Rectangle.fromDegrees(110, 20, 120, 35), // 西经、南纬、东经、北纬
  //   orientation: {
  //     heading: Cesium.Math.toRadians(0),
  //     pitch: Cesium.Math.toRadians(-45)
  //   }
  // })
})

onUnmounted(() => {
  if (viewer) {
    viewer.destroy()
    viewer = null
  }
})
</script>

<template>
  <div class="cesium-container" ref="viewerRef"></div>
</template>

<style scoped>
.cesium-container {
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}
</style>

效果说明

启动项目后,相机将直接显示北京区域10000米高度、俯视30度的视角,无任何过渡动画,视角切换瞬间完成。

2.2 方法2:flyTo(平滑飞行定位,推荐)

flyTo 方法是最常用的视角设置方式,相机将以“平滑飞行”的动画形式到达目标视角,视觉体验更友好(如初始化场景、点击定位等交互场景)。其参数与setView 基本一致,额外增加了动画相关配置。

核心参数(新增动画相关)

  • duration:可选,飞行动画持续时间(单位:秒),默认根据距离自动计算。

  • maximumHeight:可选,飞行过程中的最大高度(单位:米),避免飞行过程中视角过低或过高。

  • 其他参数(destination、orientation)与 setView 一致。

代码示例


<script setup lang="ts">
import { onMounted, ref, onUnmounted } from 'vue'
import * as Cesium from 'cesium'

const viewerRef = ref<HTMLDivElement | null>(null)
let viewer: Cesium.Viewer | null = null

onMounted(() => {
  if (!viewerRef.value) return

  viewer = new Cesium.Viewer(viewerRef.value, {
    // 沿用推荐的option参数
    homeButton: true,
    fullscreenButton: true,
    baseLayerPicker: true,
    timeline: false,
    animation: false,
    geocoder: false,
    navigationHelpButton: false,
    sceneModePicker: false,
    scene3DOnly: true,
    requestRenderMode: true,
    maximumRenderTimeChange: 0.01
  })

  // flyTo方法:平滑飞行到上海(3秒完成)
  viewer.camera.flyTo({
    destination: Cesium.Cartesian3.fromDegrees(121.4737, 31.2304, 8000), // 上海经纬度+8000米高度
    orientation: {
      heading: Cesium.Math.toRadians(10), // 航向角10°(轻微朝东)
      pitch: Cesium.Math.toRadians(-25), // 俯仰角-25°(俯视)
      roll: 0
    },
    duration: 3, // 飞行时间3秒
    maximumHeight: 12000 // 飞行过程中最高12000米
  })
})

onUnmounted(() => {
  if (viewer) {
    viewer.destroy()
    viewer = null
  }
})
</script>

效果说明

启动项目后,相机会从默认全球视角开始,以平滑的动画飞行3秒,最终到达上海8000米高度、俯视25度的视角,飞行过程中高度不超过12000米,视觉体验流畅自然。

2.3 方法3:lookAt(指向目标点,固定观察)

lookAt 方法用于将相机的视线“固定指向”某个目标点,同时设置相机的位置和姿态。适用于需要持续观察某个固定目标的场景(如观察某个建筑、标记点)。

核心参数

  • target:必选,目标点的笛卡尔坐标(被观察的点)。

  • offset:必选,相机相对于目标点的偏移量(包含位置偏移和姿态偏移)。

代码示例


<script setup lang="ts">
import { onMounted, ref, onUnmounted } from 'vue'
import * as Cesium from 'cesium'

const viewerRef = ref<HTMLDivElement | null>(null)
let viewer: Cesium.Viewer | null = null

onMounted(() => {
  if (!viewerRef.value) return

  viewer = new Cesium.Viewer(viewerRef.value, {
    // 沿用推荐的option参数
    homeButton: true,
    fullscreenButton: true,
    baseLayerPicker: true,
    timeline: false,
    animation: false,
    geocoder: false,
    navigationHelpButton: false,
    sceneModePicker: false,
    scene3DOnly: true,
    requestRenderMode: true,
    maximumRenderTimeChange: 0.01
  })

  // 1. 定义目标点:天安门(经纬度转换为笛卡尔坐标)
  const target = Cesium.Cartesian3.fromDegrees(116.397470, 39.908692, 50);

  // 2. lookAt方法:相机固定指向天安门,位置在目标点东北方向5000米、高度2000米
  viewer.camera.lookAt(
    target,
    new Cesium.Cartesian3(5000, -5000, 2000) // 偏移量:x正方向(东)5000,y负方向(北)5000,z(高度)2000
  );

  // 3. 可选:调整相机姿态(确保视线指向目标)
  viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
})

onUnmounted(() => {
  if (viewer) {
    viewer.destroy()
    viewer = null
  }
})
</script>

效果说明

相机将固定指向天安门位置,无论如何拖拽旋转视角,视线始终聚焦于天安门;相机位置固定在天安门东北方向5000米、高度2000米处,适合持续观察目标点。

2.4 方法4:手动修改Camera属性(灵活控制)

除了上述封装好的方法,也可直接修改Camera的 positionheadingpitch 等属性,实现更灵活的视角控制(如自定义动画、实时调整视角)。需注意:直接修改属性后,需调用 camera.updateCamera() 使修改生效。

代码示例


<script setup lang="ts">
import { onMounted, ref, onUnmounted } from 'vue'
import * as Cesium from 'cesium'

const viewerRef = ref<HTMLDivElement | null>(null)
let viewer: Cesium.Viewer | null = null

onMounted(() => {
  if (!viewerRef.value) return

  viewer = new Cesium.Viewer(viewerRef.value, {
    // 沿用推荐的option参数
    homeButton: true,
    fullscreenButton: true,
    baseLayerPicker: true,
    timeline: false,
    animation: false,
    geocoder: false,
    navigationHelpButton: false,
    sceneModePicker: false,
    scene3DOnly: true,
    requestRenderMode: true,
    maximumRenderTimeChange: 0.01
  })

  const camera = viewer.camera;

  // 1. 手动设置相机位置(广州经纬度+12000米高度)
  camera.position = Cesium.Cartesian3.fromDegrees(113.2644, 23.1291, 12000);

  // 2. 手动设置相机姿态
  camera.heading = Cesium.Math.toRadians(0); // 正北
  camera.pitch = Cesium.Math.toRadians(-35); // 俯视35度
  camera.roll = 0;

  // 3. 使修改生效
  camera.updateCamera();
})

onUnmounted(() => {
  if (viewer) {
    viewer.destroy()
    viewer = null
  }
})
</script>

效果说明

与 setView 类似,视角瞬间切换到广州12000米高度、俯视35度的视角,适合需要精细控制视角属性的场景。

三、常用设置方法效果对比

为了方便大家根据场景选择合适的方法,整理了4种方法的核心差异和适用场景:

设置方法核心特点适用场景视觉效果
setView无动画,瞬间定位,参数简单快速切换视角、初始化简单场景视角突变,无过渡
flyTo平滑动画,支持自定义飞行时间初始化场景、点击定位、用户交互飞行过渡自然,体验友好(推荐)
lookAt固定视线指向目标点持续观察某个目标(如建筑、标记点)视线聚焦目标,视角旋转时目标不变
手动修改属性灵活控制单个属性,需手动生效自定义动画、实时微调视角可实现复杂视角变化,需自行控制过渡

四、总结

本文基于前两篇的开发环境,详细讲解了Cesium Camera的核心概念和4种常用设置方法:

  1. Camera的核心属性(position、heading、pitch、roll)决定了视角的位置和姿态,需注意角度与弧度的转换。

  2. setView适合快速定位,flyTo适合友好的交互定位(推荐),lookAt适合固定观察目标,手动修改属性适合灵活自定义视角。

  3. 所有方法均基于现有Vue+Vite+TS环境实现,代码可直接复用,只需根据业务需求调整目标位置和姿态参数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值