【Cesium 入门】摄像头控制

1,499 阅读3分钟

【Cesium 入门】系列是将CesiumJS官网教程文章翻译为中文,同时对文章进行了一定的补充,并且提供Vue3版本的代码GitHub - cesiumjs教程的vue3版本 。希望这个系列可以帮助你更好的学习cesium。

官网地址:cesium.com/learn/cesiu…

本指南将向您展示如何在 CesiumJS 中使用相机 API 并实现诸如飞到地球上的某个点、缩放到场景中的数据源或将相机锁定到特定模型等功能。

开始前

项目搭建参考【Cesium 入门】快速开始

飞到地球上的某个点

如果你知道某个点的纬度、经度和高度,你可以使用相机的flyTo函数在CesiumJS中直接飞到该位置,有一个飞行过程的动画。例如,要飞往圣地亚哥,我们分别设置-117.16、32.71和15000.0的经度、纬度和高度:

 viewer.camera.flyTo({
     destination: Cesium.Cartesian3.fromDegrees(-117.16, 32.71, 15000.0),
 });

controlcamera_flyto.gif
在飞向一个地点后可以更改相机的方向(orientation 也可以称为姿态),不设置相机方向将指向默认方向:

viewer.camera.flyTo({
     destination: Cesium.Cartesian3.fromDegrees(-117.16, 32.71, 15000.0),
     orientation: {
       heading: Cesium.Math.toRadians(20.0),
       pitch: Cesium.Math.toRadians(-35.0),
       roll: 0.0,
     },
 });
image-20240715202205933.pngimage-20240715202221967.png
默认方向指定方向

orientation三个参数如何理解?

在这里我提供一个形象的解释:假设你现在是直立的状态(站立在地面上),或者由直立的状态垂直上升到空中。
heading是你现在面向的方向,是水平方向,东南西北,角度0°是面向正北方向,顺时针转动,角度90°是正东方向;
pitch是你抬头或者低头角度,是俯仰角度,角度0°是平视,角度90°是抬头看向头顶正上方,角度-90°是看向地面;
roll是歪头方向,将头歪向左肩膀负,将头歪向右肩膀正。
注意orientation三个参数都是弧度。

heading-pitch-roll.jpg
(图片参考:juejin.cn/post/732050…)

image-20240715204735015.pngimage-20240715204655621.png
heading -45, patch 0, roll 0heading 45, patch 0, roll 0
image-20240715204517056.pngimage-20240715204555797.png
heading 0, patch -45, roll 0heading 0, patch 45, roll 0 看向天空
image-20240715204346649.pngimage-20240715204225671.png
heading 0, patch 0, roll -45heading 0, patch 0, roll 45

缩放到场景中的数据源

如果已将资源添加到场景中并希望将摄影机聚焦在资源上(焦点没有锁死,可以平移到其他地方),同样也可以使用查看器的flyTo。viewer.flyTo函数接受Entity、EntityCollection、DataSource、Cesium3DTilset等。 例如,使用以下代码片段关注已添加到场景中的矩形实体:

 var west = -90.0;
 var south = 38.0;
 var east = -87.0;
 var north = 40.0;
 var rectangle = viewer.entities.add({
   rectangle: {
       coordinates: Cesium.Rectangle.fromDegrees(west, south, east, north),
   },
 });
 viewer.flyTo(rectangle);

image-20240715205514215.png

创建缓动函数

camera.flyTo功能的一个选项是easingFunction。缓动功能控制在相机飞行期间如何插值时间。以下代码示例将缓动函数设置为QUADRATIC_IN_OUT,以便从东京晴空塔飞往西雅图太空针塔:

 viewer.camera.flyTo({
   destination: new Cesium.Cartesian3(
     -3961951.575572026,
     3346492.0945766014,
     3702340.5336036095
   ),
   orientation: {
     direction: new Cesium.Cartesian3(
       0.8982074415844437,
       -0.4393530288745287,
       0.013867512433959908
     ),
     up: new Cesium.Cartesian3(
       0.12793638617798253,
       0.29147314437764565,
       0.9479850669701113
     ),
   },
   complete: function () {
     setTimeout(function () {
       viewer.camera.flyTo({
         destination: new Cesium.Cartesian3(
           -2304817.2435183465,
           -3639113.128132953,
           4688495.013644141
         ),
         orientation: {
           direction: new Cesium.Cartesian3(
             0.3760550186878076,
             0.9007147395506565,
             0.21747547189489164
           ),
           up: new Cesium.Cartesian3(
             -0.20364591529594356,
             -0.14862471084230877,
             0.9676978022659334
           ),
         },
         easingFunction: Cesium.EasingFunction.QUADRATIC_IN_OUT,
         duration: 5,
       });
     }, 1000);
   },
 });

controlcamera_easing.gif

看一个点

除了飞到地球上的某个点外,您还可以将相机锁定到某个点。当您想将相机的移动限制在某个区域或资源时,这很方便。 要将相机锁定到某个点,平移、缩放、旋转都是围绕这个点,请使用相机的lookAtTransform功能。以下代码片段将相机锁定到日本富士山:

 const center = Cesium.Cartesian3.fromRadians(
   2.4213211833389243,
   0.6171926869414084,
   3626.0426275055174
 );
 const transform = Cesium.Transforms.eastNorthUpToFixedFrame(center);
 viewer.scene.camera.lookAtTransform(
   transform,
   new Cesium.HeadingPitchRange(0, -Math.PI / 4, 2900)
 );

controlcamera_lookAPoint.gif

绕一点轨道运行

将相机锁定到某个点后,您可以创建相机动态观察来展示您的数据源。这可以通过使用相机的lookAtTransform函数和事件监听器来实现,绕着一点周边轨道旋转,相机一直锁定那个点:

 // Lock camera to a point
 const center = Cesium.Cartesian3.fromRadians(
   2.4213211833389243,
   0.6171926869414084,
   3626.0426275055174
 );
 const transform = Cesium.Transforms.eastNorthUpToFixedFrame(center);
 viewer.scene.camera.lookAtTransform(
   transform,
   new Cesium.HeadingPitchRange(0, -Math.PI / 8, 2900)
 );
 // Orbit this point
 viewer.clock.onTick.addEventListener(function (clock) {
   viewer.scene.camera.rotateRight(0.005);
 });
 

controlcamera_orbitpoint.gif