cesium.js 入门到精通(7)
我们说一下相机的概念:
生活中的相机是一个用来拍照的设备,而这里的相机应该理解成一个人机交互的媒介。地图的缩放、平移、旋转,以及相关的鼠标操作都是由相机作为媒介来实现的。相机的位置和姿态参数决定了我们能看到的地图的样子。
可以把使用 Cesium 浏览地图的过程想象成这样一个场景:
一个带有相机的能实时传回拍摄画面的无人机在地球上空飞翔。当我们在 Cesium 程序上操作鼠标的时候,无人机就会执行相关的飞行动作,并实时拍摄照片回传到程序,于是我们看到了预期的地图。在这个过程中,无人机的姿态、位置决定了相机的位置,从而决定了我们能看到什么样的地图。
二、理解相机常用参数
相机由位置(position)、姿态(orientation)和视锥体(frustum)定义。[1]
相机的三个关键参数中 position、orientation 最常用,其中 orientation 不太好理解。
orientation
由 heading
、pitch
、roll
三个参数构成,他们的单位都是弧度。在 Camera API 中没有 orientation
属性,只有 heading
、pitch
、roll
三个相关的属性。这三个属性怎么理解呢?看一张图就明白了。
假设把人绑在相机上,差不多就是这个效果。
三个姿态参数的含义以及取值范围如下:
heading: 相机的偏航角。取值范围 [-π/2
, π/2
]。
取值及其效果:
-π/2
:向左旋转 90 度;-π/4
:向左旋转45度;0
:不旋转;π/2
:向右旋转 90 度;π/4
:向右旋转45度;
pitch: 相机的俯仰角。取值范围 [-π/2
, 0
]。
取值及其效果:
-π/2
:俯视地面;-π/4
:斜向下45度俯视地面;0
:平视前方,将看不到地图;
roll: 相机的翻滚角。取值范围 [0
, π
]。
取值一般都是 0
。
三、调用相机功能的方式
1. 直接调用
可以从 Viewer 和 Scene 的实例上获取到相机实例,然后实现相关功能。
- 从 Viewer 实例上获取:
viewer.camera
。 - 从 Scene 实例上获取:
scene.camera
。
测试发现从 Viewer 和 Scene 的实例中获取到的相机对象是一样的。
Cesium 中有相机类,但是使用时一般不会去执行 new Camera()
。
2. 间接调用
有些时候,不用获取相机实例也可调用相机的功能。例如viewer.flyTo
、viewer.zoomTo
等。
<template>
<div id="cesiumContainer" ref="cesiumContainer"></div>
</template>
<script setup>
// yarn add cesium
// 将cesium目录下的Build/Cesium4个目录拷贝到public,然后将widgets目录拷贝一份到src下
import * as Cesium from "cesium";
import "./Widgets/widgets.css";
import { onMounted } from "vue";
// 设置cesium token
Cesium.Ion.defaultAccessToken =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJhMzNkNTE5Zi1mMjY4LTRiN2QtOTRlZC1lOTUyM2NhNDYzNWYiLCJpZCI6NTU0OTYsImlhdCI6MTYyNTAyNjMyOX0.a2PEM4hQGpeuMfeB9-rPp6_Gkm6O-02Dm4apNbv_Dlk";
// 设置cesium静态资源路径
window.CESIUM_BASE_URL = "/";
// 设置cesium默认视角
Cesium.Camera.DEFAULT_VIEW_RECTANGLE = Cesium.Rectangle.fromDegrees(
// 西边的经度
89.5,
// 南边维度
20.4,
// 东边经度
110.4,
// 北边维度
61.2
);
onMounted(() => {
var viewer = new Cesium.Viewer("cesiumContainer", {
// 是否显示信息窗口
infoBox: false,
});
// 隐藏logo
viewer.cesiumWidget.creditContainer.style.display = "none";
// setview瞬间到达指定位置,视角
// 生成position是天安门的位置
var position = Cesium.Cartesian3.fromDegrees(116.393428, 39.90923, 100);
// viewer.camera.setView({
// // 指定相机位置
// destination: position,
// // 指定相机视角
// orientation: {
// // 指定相机的朝向,偏航角
// heading: Cesium.Math.toRadians(0),
// // 指定相机的俯仰角,0度是竖直向上,-90度是向下
// pitch: Cesium.Math.toRadians(-20),
// // 指定相机的滚转角,翻滚角
// roll: 0,
// },
// });
// flyto,让相机飞往某个地方
viewer.camera.flyTo({
destination: position,
orientation: {
heading: Cesium.Math.toRadians(0),
pitch: Cesium.Math.toRadians(-20),
roll: 0,
},
});
});
</script>
<style>
* {
margin: 0;
padding: 0;
}
#cesiumContainer {
width: 100vw;
height: 100vh;
}
</style>
我直接让这个 相机 飞到 天安门广场了
在 CesiumJS 中,viewer.camera.setView()
和 viewer.camera.flyTo()
是两个用于控制相机位置和视角的函数,但它们的行为有所不同。
-
viewer.camera.setView()
:这个函数会立即将相机的位置和视角设置到指定的位置。它不会创建平滑的过渡效果,而是直接跳转到新的位置和视角。这对于需要立即改变视图而不希望用户看到过渡过程的场景很有用。javascript复制代码
viewer.camera.setView({
destination: position, // 指定相机位置
orientation: {
heading: Cesium.Math.toRadians(0), // 相机朝向的偏航角(东向为0度)
pitch: Cesium.Math.toRadians(-20), // 相机视角的俯仰角(竖直向上为0度,-90度为向下)
roll: 0, // 相机视角的滚转角(翻滚角)
}
});
-
viewer.camera.flyTo()
:这个函数会使相机平滑地飞往指定的位置和视角。它会创建一个过渡效果,使得相机从当前位置和视角逐渐变化到新的位置和视角。这对于提高用户体验,让用户看到从一个地点到另一个地点的移动过程非常有用。javascript复制代码
viewer.camera.flyTo({
destination: position, // 指定相机飞往的目的地位置
orientation: {
heading: Cesium.Math.toRadians(0), // 相机朝向的偏航角
pitch: Cesium.Math.toRadians(-20), // 相机视角的俯仰角
roll: 0, // 相机视角的滚转角
},
// 还可以添加其他参数,如持续时间(duration)来控制飞行时间
});
注意:
Cesium.Math.toRadians()
函数用于将角度从度转换为弧度,因为 CesiumJS 内部使用弧度作为角度的度量单位。- 在使用
flyTo()
方法时,可以通过添加额外的参数(如duration
)来控制飞行过渡的持续时间,以毫秒为单位。如果不指定,Cesium 会使用默认的飞行时间。 position
变量应该是一个Cesium.Cartesian3
类型的对象,表示相机要飞往的地球表面或空间中的位置。你可以通过经纬度(使用Cesium.Cartesian3.fromDegrees()
)或其他方式计算这个位置。
选择使用 setView()
还是 flyTo()
取决于你的具体需求,是需要立即改变视图还是需要一个平滑的过渡效果。