CesiumJS 相机(Camera)操作技巧

936 阅读3分钟

原文地址:Control the Camera – Cesium

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

前提条件

了解如何设置一个基本的 CesiumJS 应用程序。

如果您还不知道如何设置,可以阅读 CesiumJS 快速入门 / CesiumJS 快速入门 - 掘金 (juejin.cn) 教程。

飞到某个地点

如果您知道该地点的经度、纬度和高度,可以使用相机的 flyTo 函数直接飞到该地点。例如,要飞到圣地亚哥,我们传入 -117.16、32.71 和 15000.0 分别作为经度、纬度和高度:

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

要在 flyTo 完成后改变相机的方向,需要添加一个 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,
    },
});

这里的航向(heading)、俯仰(pitch)和翻滚(roll)分别相对于东、北和上。

获取点的位置

如果您知道想飞到的位置的名称,但不确定该位置的坐标,可以使用 pickPosition 来查找。以下代码段将在点击时打印出该点的位置(注意:输出的是 Cartesian3 格式,而不是经纬度信息):

var handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
handler.setInputAction(function (event) {
  var pickedPosition = viewer.scene.pickPosition(event.position);
  if (Cesium.defined(pickedPosition)) {
    console.log(pickedPosition);
  }
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

飞到某个资产

如果您已在场景中添加了一个资产,并希望将相机聚焦于该资产上,可以使用视图的 flyTo 函数。viewer.flyTo 函数接受 EntityEntityCollectionDataSourceCesium3DTileset 等多种类型。

例如,以下代码段将相机聚焦于已经添加到场景中的矩形 Entity

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);

创建缓动函数

camera.flyTo 函数的一个选项是 easingFunction,它用于控制相机飞行过程中时间的插值方式。以下代码示例展示了将缓动函数设置为 QUADRATIC_IN_OUT,以实现从东京晴空塔(Tokyo Skytree)飞到西雅图太空针塔(Seattle Space Needle)的效果:

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);
  },
});

锁定到一个点

除了可以飞到某个点外,您还可以将相机锁定到某个点。这在您想将相机的移动限制到一个区域或资产时非常有用。

要将相机锁定到一个点,请使用相机的 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)
);

围绕一个点旋转

将相机锁定到一个点后,您可以创建一个相机轨道以 360° 旋转的方式展示您的资产。上述功能可以通过 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 / 8, 2900)
);
// 绕点旋转
viewer.clock.onTick.addEventListener(function (clock) {
  viewer.scene.camera.rotateRight(0.005);
});

1

ScreenSpaceCameraController 相机控制器对象

ScreenSpaceCameraController 以屏幕上的用户输入(鼠标拖拽点击或者触摸事件)来修改相机的位置和方向。 它包含一些属性,可以启用/禁用操作、修改惯性、最小最大缩放距离等。

例如,您可以使用 ScreenSpaceCameraController 来控制是否允许相机进入地下:

// 禁止旋转相机
viewer.scene.screenSpaceCameraController.enableRotate = false;
// 禁止倾斜相机
viewer.scene.screenSpaceCameraController.enableTilt = false;
// 禁止平移相机
viewer.scene.screenSpaceCameraController.enableTranslate = false;
// 禁止缩放相机
viewer.scene.screenSpaceCameraController.enableZoom = false;
// 禁用相机碰撞以允许其进入地下
viewer.scene.screenSpaceCameraController.enableCollisionDetection = false;

其他资源

请查看 Sandcastle 中有关 Camera 部分的示例:

  • Camera Tutorial —— 控制相机移动的代码示例。
  • Camera —— 飞到各个位置、查看范围和设置相机参考系的代码示例。

另外,可以阅读相关API文档: