引言
本教程主要是围绕Cesium这一开源三维框架开展的可视化项目教程。总结一下相关从业经验,如果有什么疑问或更好的见解,欢迎评论、私聊探讨,共同进步。教程依托于vue3前端框架,参考初始化内容:【WebGis开发 - Cesium】三维可视化项目教程—初始化场景
本篇主要讨论如何完成视点管理功能。视点(有的地方也叫收藏点)信息存储了特定视角的相机数据,可以将镜头移动至最佳视角观察三维场景。通常会有以下应用场景:
- 三维场景的初始化视角,通常情况下三维可视化项目都是针对一个园区、片区、城市等多种范围而立项的。所以针对这些范围设置并保存一个最佳视角是非常重要的。
- POI点保存视点信息,在一个范围内可能有多个亮点项目或独特建筑,设置POI点时绑定视点信息,通过点选POI点将镜头移动至最佳观察点。
- 纯收藏功能,把一些项目好看的角度都保存下来并截图,提供汇报工作时演示。
先看效果:
一、基础功能探索
1. 镜头视角获取
在初始化Cesium场景后,通常会设置全局变量 viewer
。我们通过 viewer.camera
来获取镜头信息。主要获取 position
、heading
、pitch
、roll
这四个属性:
- position,笛卡尔坐标系下的相机位置坐标。
- heading,表示左右摇头。
- pitch,表示上下点头。
- roll,表示左右歪头。一般情况下,为了减少用户眩晕感,将roll值默认为0。
{
position:{
"x": -2392730.83864336,
"y": 5412946.353618708,
"z": 2439801.3235747567
},
heading: 6.283185307179586,
pitch: -1.5695637657002988,
roll: 0,
// 其他信息
}
2. 镜头视角移动
这里使用 viewer.camera
的 flyTo
方法,控制视角移动至特定视角。
主要使用到两个参数:
- destination,接收一个笛卡尔坐标系的x、y、z三参数对象。表示镜头目标坐标点。
- orientation,偏航角(heading)、俯仰角(pitch)和倾斜角(roll)属性的对象,或包含方向(direction )和向上(up)属性的对象。一般使用前者。
- 其他属性通过查阅cesium api示例研究。
viewer.camera.flyTo({
destination: {
x: -2392668.884812449,
y: 5404950.676815235,
z: 2436590.0523108398,
},
orientation: {
heading: 6.283185307179586,
pitch: -1.5695637656997583,
roll: 0,
},
});
至此你已经可以获取镜头数据以及控制镜头移动了。
二、进一步封装代码
先理清楚使用场景,需要一个获取视角的方法,一个设置视角的方法,最好可以告诉用户视角移动完成。
1. 封装hooks函数
解释下封装函数的内容
- 设置
currentView
变量 ,用作响应式的赋值当前选中视点信息。 - 设置
isFlying
变量,用于给定视角移动的标识。利用这一标识,可以规避一些误操作。 getView
函数,获取当前视角的镜头信息。只保留需要的部分,并返回字符串形式数据,用于业务存储数据。setView
函数,设置视角,返回promise对象。使用链式调用或者await,可以更方便的获得移动完成的时间点,方便进行下一步操作。同时支持自定义移动周期以及运动的缓动函数。- 其他参数在后续的深入研究后,结合业务场景判断是否需要集成到当前hooks函数中。
在 src/hooks
目录下添加 useViewManager.js 文件
import { ref } from "vue";
export const useViewManager = () => {
// 当前获取的视点信息
const currentView = ref(null);
// 是否在视角移动过程中
const isFlying = ref(false);
/**
* @description: 获取当前视点信息
* @return { string } 返回当前视点信息,使用JSON.stringify转换为字符串
*/
const getView = () => {
const cameraData = viewer.camera;
currentView.value = JSON.stringify({
destination: cameraData.position.clone(),
orientation: {
heading: cameraData.heading,
pitch: cameraData.pitch,
roll: cameraData.roll,
},
});
return currentView.value;
};
/**
* @description: 设置视角
* @param {*} view 视点信息,由getView方法获取的字符串
* @param {*} duration 移动时间
* @param {*} easingFunction 缓动函数
* @return {*}
*/
const setView = (view, duration = 1.5, easingFunction) => {
return new Promise((resolve, reject) => {
isFlying.value = true;
const cameraData = JSON.parse(view);
viewer.camera.flyTo({
...cameraData,
duration,
complete: () => {
isFlying.value = false;
resolve(true);
},
cancel: () => {
isFlying.value = false;
reject(false);
},
// 缓动函数枚举值参考链接: https://cesium.com/learn/cesiumjs/ref-doc/EasingFunction.html?classFilter=EasingFunction
// 你也可以自己编写缓动函数,注意函数返回值在[0,1]区间内即可。
easingFunction: easingFunction || Cesium.EasingFunction.LINEAR_NONE,
});
});
};
return {
currentView,
isFlying,
getView,
setView,
};
};
2. 如何使用该hooks函数
以下为最基础的使用方式,通过两个点击按钮去获取、设置视角。在业务中注意结合数据存储、获取等操作,灵活使用。
<script setup>
import { useViewManager } from "@/hooks/useViewManager.js";
const { getView, setView, currentView, isFlying } = useViewManager();
let viewData = "";
// 获取视角点击事件
const getCamera = () => {
viewData = getView();
};
// 设置视角点击事件
const setCamera = () => {
setView(viewData , 2).then((res) => {
console.log("fly complete ", res);
// 执行其他操作
});
};
// 设置视角点击事件(同步)
const setCameraSync = async () => {
await setView(viewData , 2);
console.log("fly complete ");
// 执行其他操作
};
</script>
三、总结
本篇主要介绍了如何利用 viewer.camera
和 flyTo
完成了视点管理模块必备功能的hooks函数封装。完整的视点管理还需结合后台数据存储,业务数据绑定等等复杂逻辑,这就需要你自行判断如何将本篇的hooks函数应用到业务中去。
视点管理或是视角控制,是三维可视化项目中的重点功能。这个功能优化好了,可以让项目操作起来更加丝滑令人舒适。有一些可以探索优化的点:
- 飞行路径的修正,目前是由cesium框架默认计算的飞行路径,没有进行人为干预,可以尝试
maximumHeight
、pitchAdjustHeight
、flyOverLongitude
、flyOverLongitudeWeight
这几个参数去优化路径。 - 飞行缓动效果优化,通过尝试
easingFunction
自行编写缓动函数,优化飞行速度。 - 感兴趣可以一起讨论研究下。
再接再厉~