之前有一篇文章介绍如何使用Cesium倾斜相机视角观察物体,后面发现了一个API viewer.camera.flyToBoundingSphere
,能直接实现我想要的效果。
所以我封装了一个函数,通过使用 Cesium.Camera.flyToBoundingSphere
API,自动调整相机的位置和视角,实现相机飞向指定的包围球并观察目标物体的效果。该函数可根据目标的边界自动计算最佳的相机距离,实现便捷的倾斜视角观察。
功能特点
- 自动计算目标的包围球并调整相机距离
- 支持自定义相机俯仰角和缩放因子
- 使用
Promise
异步处理,操作完成后触发回调
参数说明
参数 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
boundary | Array |
无 | 是 | 边界点数组,每两个元素表示一个经纬度坐标 |
pitch | Number |
无 | 是 | 相机俯仰角(以度为单位),用于设置相机观察角度 |
scaleFactor | Number |
0.5 | 否 | 缩放因子,用于调整目标在视野中的大小 |
返回值
返回一个 Promise
对象,在相机飞行完成后解析。
示例代码
javascript
// 使用示例
flyToBoundingSphere({
boundary:[116.3913, 39.9075, 116.4013, 39.9175], // 北京坐标示例
pitch: 45, // 设置俯仰角为45度
scaleFactor: 0.7 // 缩小视图中的物体大小
}).then(() => {
console.log('相机飞行完成');
}).catch(error => {
console.error('相机飞行失败:', error);
});
函数源码
js
/**
* 将相机飞向指定的包围球,并自动调整相机位置和视角。
*
* @param {Object} options - 配置选项
* @param {Array} options.boundary - 边界点数组,每两个元素表示一个经纬度坐标
* @param {Number} options.pitch - 相机俯仰角(以度为单位)
* @param {Number} [options.scaleFactor=0.5] - 缩放因子,用于调整目标的观察大小
* @returns {Promise} - 返回一个Promise对象,在相机飞行完成后解析
*/
function flyToBoundingSphere(options) {
return new Promise((resolve, reject) => {
try {
const { boundary, pitch, scaleFactor = 0.5 } = options;
const boundingSphere = getBoundingSphere(boundary);
// 调整包围球的半径,根据 scaleFactor 放大或缩小视图中的物体大小
boundingSphere.radius *= 1 / scaleFactor;
// 计算合适的相机高度
const distance =
boundingSphere.radius / Math.sin(viewer.camera.frustum.fov / 2);
// 自动调整相机以确保包围球在视野内
viewer.camera.flyToBoundingSphere(boundingSphere, {
duration: 2, // 单位秒
offset: new Cesium.HeadingPitchRange(
Cesium.Math.toRadians(360),
Cesium.Math.toRadians(pitch), // 设置相机俯仰角
distance, // 计算合适的距离
),
complete: () => {
resolve();
},
});
} catch (e) {
reject(e);
}
});
}
/**
* 计算包含指定边界点的包围球。
*
* @param {Array} boundary - 边界点数组,每两个元素表示一个经纬度坐标
* @returns {Cesium.BoundingSphere} - 包围球对象
*/
function getBoundingSphere(boundary) {
// 将边界点转换为 Cartesian3 坐标
const positions = [];
for (let i = 0; i < boundary.length; i += 2) {
const lon = boundary[i];
const lat = boundary[i + 1];
const position = Cesium.Cartesian3.fromDegrees(lon, lat);
positions.push(position);
}
// 计算包含所有边界点的包围球
return Cesium.BoundingSphere.fromPoints(positions);
}