本指南将向您展示如何使用 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 函数接受 Entity、EntityCollection、DataSource、Cesium3DTileset 等多种类型。
例如,以下代码段将相机聚焦于已经添加到场景中的矩形 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);
});
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文档: