Cesium相机的使用(四)

在 Cesium 开发中,相机是我们与三维地球交互的核心载体,它决定了我们观察三维场景的视角、范围和姿态。在前几篇文章中,我们已经了解了相机的基础配置、视角定位等核心功能,本篇将聚焦于相机的精细化初始配置、平滑飞行定位以及自定义键盘交互控制。

目录

[​编辑一、Cesium 相机核心配置:初始视角与缩放限制](#编辑一、Cesium 相机核心配置:初始视角与缩放限制)

1.相机缩放距离限制

2.两种初始视角定位方式

二、自定义键盘交互:全方位控制相机姿态

1.核心设计思路

2.核心相机方法说明

3.键盘交互逻辑

三、完整代码展示


一、Cesium 相机核心配置:初始视角与缩放限制

1.相机缩放距离限制

通过camera.minimumZoomDistancecamera.maximumZoomDistance可以设置相机的最小 / 最大缩放距离(单位:米),防止用户缩放过近导致场景失真,或缩放过远超出业务所需范围:

复制代码
// 获取场景对象与相机对象
const scene = viewer.scene
const camera = scene.camera

// 设置相机缩放距离限制
camera.minimumZoomDistance = 1000 // 最小缩放距离:1000米
camera.maximumZoomDistance = 5000000 // 最大缩放距离:500万米(5000公里)

2.两种初始视角定位方式

提供了两种常用的相机初始定位方式,分别适用于不同的业务场景。

关键参数说明:

Cartesian3.fromDegrees(lng, lat, height):将地理坐标系(经纬度 + 高度)转换为 Cesium 支持的笛卡尔直角坐标系,是相机定位的核心方法。

|---------|-----------------------------------------------------------------------|
| 参数 | 功能描述 |
| heading | 水平航向角,以正北为 0 度,顺时针旋转为正,范围 0~360 度(需通过Cesium.Math.toRadians()转换为弧度) |
| pitch | 俯仰角,控制相机的俯视 / 仰视角度,-90 度为垂直向下俯视,0 度为水平视角,90 度为垂直向上仰视 |
| roll | 翻滚角,控制相机的左右倾斜,一般保持 0 度即可,避免场景出现倾斜失真 |

方式一:直接设置视角(无过渡动画)

使用camera.setView()方法可以直接将相机定位到目标区域,无过渡效果,加载速度快,适用于需要快速渲染初始视角的场景:

复制代码
// 以江苏省中心点(经度、纬度、高度)
const center = Cesium.Cartesian3.fromDegrees(119.8, 32.9, 20000)

// 直接设置相机视角聚焦江苏省
viewer.camera.setView({
  destination: center, // 视角目标点(中心点+高度)
  orientation: { // 相机姿态配置
    heading: Cesium.Math.toRadians(0), // 水平方向角度(0为正北,顺时针递增)
    pitch: Cesium.Math.toRadians(-40), // 俯视角度(-90为垂直向下,0为水平,90为垂直向上)
    roll: Cesium.Math.toRadians(0) // 翻滚角度(一般保持0,避免场景倾斜)
  }
})

方式二:平滑飞行定位(带过渡动画)

使用camera.flyTo()方法可以实现相机从当前视角平滑飞行到目标视角,带有过渡动画,用户体验更友好,还可以通过duration设置飞行时长(单位:秒):

复制代码
// 以江苏省中心点(经度、纬度、高度)
const center = Cesium.Cartesian3.fromDegrees(119.8, 32.9, 20000)

// 平滑飞行定位到江苏省(推荐,用户体验更优)
viewer.camera.flyTo({
  destination: center, // 视角目标点(中心点+高度)
  orientation: { // 相机姿态配置
    heading: Cesium.Math.toRadians(0), // 水平方向角度(正北)
    pitch: Cesium.Math.toRadians(-10) // 俯视角度(轻微俯视,更清晰展示区域范围)
  },
  duration: 5 // 飞行过渡时间:5秒
})

二、自定义键盘交互:全方位控制相机姿态

Cesium 相机提供了丰富的姿态控制方法,我们可以通过监听键盘事件,实现自定义按键控制相机的移动、旋转、翻滚,让相机操作更符合用户的使用习惯,这也是三维场景交互的核心功能之一。

1.核心设计思路

(1)监听全局keydown事件,捕获用户按键操作;

(2)以相机当前离地高度为基准计算移动速度(moveRate = height/100),实现 "远快近慢" 的自适应移动效果,提升操作手感;

(3)映射不同按键到对应的相机方法,实现全方位交互控制。

2.核心相机方法说明

|----------------------------------------------|-------------|--------------|
| 相机方法 | 功能描述 | 适用场景 |
| moveForward(moveRate) | 相机沿当前视角向前平移 | 靠近目标物体 |
| moveBackward(moveRate) | 相机沿当前视角向后平移 | 远离目标物体 |
| moveLeft(moveRate) / moveRight(moveRate) | 相机左右平移 | 侧方观察场景 |
| moveUp(moveRate) / moveDown(moveRate) | 相机上下平移 | 调整相机离地高度 |
| lookLeft(rad) / lookRight(rad) | 相机左右旋转视角 | 水平方向环视场景 |
| lookUp(rad) / lookDown(rad) | 相机上下旋转视角 | 垂直方向观察场景 |
| twistLeft(rad) / twistRight(rad) | 相机左右翻滚 | 模拟飞行器倾斜等特殊场景 |

3.键盘交互逻辑

复制代码
// 通过按键移动/旋转/翻滚相机
document.addEventListener('keydown', (event) => {
  // 获取相机当前离地高度
  var height = viewer.camera.positionCartographic.height
  // 设置自适应移动速度(远快近慢)
  var moveRate = height / 100
  
  // 相机平移控制(前后左右上下)
  if (event.key === 'w') {
    viewer.camera.moveForward(moveRate) // 向前平移
  } else if (event.key === 's') {
    viewer.camera.moveBackward(moveRate) // 向后平移
  } else if (event.key === 'a') {
    viewer.camera.moveLeft(moveRate) // 向左平移
  } else if (event.key === 'd') {
    viewer.camera.moveRight(moveRate) // 向右平移
  } else if (event.key === 'q') {
    viewer.camera.moveUp(moveRate) // 向上平移
  } else if (event.key === 'e') {
    viewer.camera.moveDown(moveRate) // 向下平移
  }
  
  // 相机视角旋转控制(左右上下)
  else if (event.key === 'z') {
    viewer.camera.lookLeft(Cesium.Math.toRadians(0.1)) // 向左旋转视角
  } else if (event.key === 'c') {
    viewer.camera.lookRight(Cesium.Math.toRadians(0.1)) // 向右旋转视角
  } else if (event.key === 'x') {
    viewer.camera.lookUp(Cesium.Math.toRadians(0.1)) // 向上旋转视角
  } else if (event.key === 'v') {
    viewer.camera.lookDown(Cesium.Math.toRadians(0.1)) // 向下旋转视角
  }
  
  // 相机翻滚控制(左右倾斜)
  else if (event.key === 'r') {
    viewer.camera.twistLeft(Cesium.Math.toRadians(0.1)) // 向左逆时针翻滚
  } else if (event.key === 'f') {
    viewer.camera.twistRight(Cesium.Math.toRadians(0.1)) // 向右顺时针翻滚
  }
})

三、完整代码展示

复制代码
<template>
  <div id="cesiumContainer"></div>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import * as Cesium from 'cesium'

//设置cesiumtoken
Cesium.Ion.defaultAccessToken =
  '你的token'

//设置cesium默认视角--该视角打开时地球中心点位置位于中国
Cesium.Camera.DEFAULT_VIEW_RECTANGLE = Cesium.Rectangle.fromDegrees(
  //西边
  89.5,
  //南边
  20.4,
  //东边
  110.4,
  //北边
  61.2
)
const initMapCesium = () => {
  const viewer = new Cesium.Viewer('cesiumContainer', {
    infoBox: false, //是否显示信息框
    geocoder: false, //位置查找工具
    homeButton: false, //是否显示首页位置工具
    sceneModePicker: false, //是否显示视角模式切换工具
    baseLayerPicker: false, //是否显示默认图层选择工具
    navigationHelpButton: false, //是否显示导航帮助工具
    animation: false, //是否显示动画工具
    timeline: false, //是否显示时间轴工具
    fullscreenButton: false //是否显示全屏按钮工具
  })
  viewer.cesiumWidget.creditContainer.style.display = 'none' //隐藏cesium版权信息

  //设置地图的初始视角
  const scene=viewer.scene//获取场景对象
  const camera=scene.camera//获取相机对象

  camera.minimumZoomDistance = 1000 //最小缩放距离
  camera.maximumZoomDistance = 5000000 //最大缩放距离

  //地图中心点位置--江苏省
  const center=Cesium.Cartesian3.fromDegrees(119.8, 32.9, 20000) //设置初始视角的中心点--fromDegrees(经度,纬度,高度)
  // 设置初始视角聚焦江苏省(高度500公里,俯视角度)--第一种方式
  // viewer.camera.setView({
  //   destination: center,//设置视角的目标点
  //   orientation: {//设置视角的方向
  //     heading: Cesium.Math.toRadians(0), // 水平方向角度(0为正北)
  //     pitch: Cesium.Math.toRadians(-40), // 俯视角度(-90为垂直向下)
  //     roll: Cesium.Math.toRadians(0) // 翻滚角度
  //   }
  // })

  //第二种方式--用矩形范围精确框定江苏省
   viewer.camera.flyTo({
    destination: center,
    orientation: {
      heading: Cesium.Math.toRadians(0),
      pitch: Cesium.Math.toRadians(-10)
    },
    duration: 5 // 飞行时间(秒)
   })


  //通过按键移动相机
  document.addEventListener('keydown', (event) => {
    //获取相机与地面的高度
    var height = viewer.camera.positionCartographic.height
    //设置移动速度
    var moveRate=height/100
    if (event.key === 'w') {
      //设置相机向前移动
      viewer.camera.moveForward(moveRate)
    } else if (event.key === 's') {
      //设置相机向后移动
      viewer.camera.moveBackward(moveRate)
    } else if (event.key === 'a') {
      //设置相机向左移动
      viewer.camera.moveLeft(moveRate)
    } else if (event.key === 'd') {
      //设置相机向右移动
      viewer.camera.moveRight(moveRate)
    } else if (event.key === 'q') {
      //设置相机向上移动
      viewer.camera.moveUp(moveRate)
    } else if (event.key === 'e') {
      //设置相机向下移动
      viewer.camera.moveDown(moveRate)
    } else if (event.key === 'z') {
      //设置相机向左旋转
      viewer.camera.lookLeft(Cesium.Math.toRadians(0.1))
    } else if (event.key === 'c') {
      //设置相机向右旋转
      viewer.camera.lookRight(Cesium.Math.toRadians(0.1))
    } else if (event.key === 'x') {
      //设置相机向上旋转
      viewer.camera.lookUp(Cesium.Math.toRadians(0.1))
    } else if (event.key === 'v') {
      //设置相机向下旋转
      viewer.camera.lookDown(Cesium.Math.toRadians(0.1))
    } else if (event.key === 'r') {
      //向左逆时针翻滚
      viewer.camera.twistLeft(Cesium.Math.toRadians(0.1))
    }else if (event.key === 'f') {
      //向右顺时针翻滚
      viewer.camera.twistRight(Cesium.Math.toRadians(0.1))
    }
  })

  // 监听相机位置变化,获取当前缩放等级(高度)
  viewer.scene.postRender.addEventListener(() => {
    // const currentHeight = Cesium.Cartographic.fromCartesian(camera.position).height
    // console.log('当前缩放高度:', currentHeight, '米')
  })



}

onMounted(() => {
  initMapCesium()
})
</script>

<style lang="less" scoped>
#cesiumContainer {
  overflow: hidden;
  width: 100vw;
  height: 100vh;
}
</style>

四、结果展示

相关推荐
跳跳糖炒酸奶3 小时前
基于深度学习的单目深度估计综述阅读(1)
人工智能·深度学习·数码相机·单目深度估计
木头程序员4 小时前
算摄像学的“算法-传感器”协同设计:重新定义光学极限
人工智能·数码相机·硬件工程
shejizuopin5 小时前
基于多鱼眼的视觉SLAM系统(毕业论文)
人工智能·数码相机·目标跟踪·毕业论文·答辩ppt·基于多鱼眼的·视觉slam系统
国科安芯5 小时前
微小卫星红外相机双MCU冗余架构的抗辐照可靠性评估
人工智能·单片机·嵌入式硬件·数码相机·架构·自动化·安全性测试
摘星编程7 小时前
React Native for OpenHarmony 实战:Camera 相机组件详解
数码相机·react native·react.js
_李小白1 天前
【Android 美颜相机】第六天:GPUImageView解析
android·数码相机
carver w1 天前
张氏相机标定,不求甚解使用篇
c++·python·数码相机
_李小白2 天前
【Android 美颜相机】第二天:Android-GPUImage Sample模块源码解析
android·数码相机
双翌视觉2 天前
机器视觉引导如何实现机械手的动态抓取
人工智能·数码相机