该类主要用于监听键盘事件并在用户按下不同按键时执行相应的相机操作,如改变相机的位置、偏航角、俯仰角和翻滚角,从而实现在三维场景中的漫游。
以下是代码的主要逻辑:
导入Cesium库,并定义一个flags
对象,其中包含了所有可能触发的键盘漫游状态标志。
keyboardRoam
类包含以下方法:
start(viewer, setStep)
: 初始化键盘监听事件,包括keydown和keyup事件,并在每一帧(clock onTick事件)中执行funcTick
函数以更新相机状态。同时禁用默认的鼠标移动地图和平移相机的功能。
hprSetting(h, p, r)
: 设置相机的Heading、Pitch、Roll(即偏航角、俯仰角、翻滚角)。
getFlagFromKeyboard(k)
: 根据按下的键盘按键返回对应的按键名称。
在funcTick
函数中,根据flags
对象中的状态标志来更新相机的位置和姿态。
quit()
方法用于销毁键盘监听事件以及恢复鼠标移动地图和平移相机的功能。
通过实例化 keyboardRoam
类并调用 start
方法,可以启用键盘漫游功能;调用 quit
方法则停止漫游并恢复默认的相机控制方式。
// 引入键盘漫游方法
import keyboardRoam from "../utils/roam/keyboardRoam";
// 键盘控制相机方法初始化
keyboard = new keyboardRoam();
// 键盘控制相机方法开始
keyboard.start(window.viewer, 1)
// 键盘控制相机方法结束
keyboard.quit();
import * as Cesium from "cesium";
// 定义事件组
let flags = {
// 相机位置
moveForward: false,
moveBackward: false,
moveLeft: false,
moveRight: false,
moveUp: false,
moveDown: false,
translateFront: false,
translateBehind: false,
// 相机姿态
picthUp: false,
picthDown: false,
rollLeft: false,
rollRight: false,
headingLeft: false,
headingRight: false,
};
let cameraHeight;
let heading;
let pitch;
let roll;
let funcTick;
/**
* 键盘漫游
*/
class keyboardRoam {
/**
* 键盘漫游加载方法
* @param: 使用键盘控制地图漫游,
* @param {Cesium.Viewer} viewer -cesium地图容器
* @param {Number} setStep -相机视角移动步长
*/
start(viewer, setStep) {
let that = this;
// 添加键盘监听事件
document.addEventListener(
"keydown",
(this.down = function (e) {
let flagName = that.getFlagFromKeyboard(e);
if (typeof flagName !== "undefined") {
flags[flagName] = true;
}
}),
false
);
// 相机将保持锁定在当前位置。此标志仅适用于2D和Columbus视图模式。
viewer.scene.screenSpaceCameraController.enableTranslate = false;
// 相机将锁定到当前标题。这个标志只适用于3D和哥伦布视图。
viewer.scene.screenSpaceCameraController.enableTilt = false;
document.addEventListener(
"keyup",
(this.up = function (e) {
let flagName = that.getFlagFromKeyboard(e);
if (typeof flagName !== "undefined") {
flags[flagName] = false;
}
}),
false
);
console.log(funcTick, '0000');
// 为每一帧添加监听事件
let m = viewer.clock.onTick.addEventListener( // 键盘按下事件
funcTick = () => {
let camera = viewer.camera;
let ellipsoid = viewer.scene.globe.ellipsoid;
cameraHeight = ellipsoid.cartesianToCartographic(camera.position).height;
// 根据相机高度设置移动距离
let moveRate = (cameraHeight / 150.0) * setStep;
heading = viewer.camera.heading;
pitch = viewer.camera.pitch;
roll = viewer.camera.roll;
// 根据事件调整相机
// 相机的偏航角、翻滚角和俯仰角
// 偏航角
if (flags.headingLeft) {
that.hprSetting(-0.005 * setStep, 0, 0);
}
if (flags.headingRight) {
that.hprSetting(0.005 * setStep, 0, 0);
}
// 俯仰角
if (flags.picthUp) {
that.hprSetting(0, 0.01 * setStep, 0);
}
if (flags.picthDown) {
that.hprSetting(0, -0.01 * setStep, 0);
}
// 翻滚角
if (flags.rollLeft) {
that.hprSetting(0, 0, 0.01 * setStep);
}
if (flags.rollRight) {
that.hprSetting(0, 0, -0.01 * setStep);
}
// 向中心点靠近
if (flags.moveForward) {
camera.moveForward(moveRate);
}
// 从中心点远离
if (flags.moveBackward) {
camera.moveBackward(moveRate);
}
// 相机本身前后左右上下平移
if (flags.moveUp) {
camera.moveUp(moveRate);
}
if (flags.moveDown) {
camera.moveDown(moveRate);
}
if (flags.moveLeft) {
camera.moveLeft(moveRate);
}
if (flags.moveRight) {
camera.moveRight(moveRate);
}
// 相机向前平移
if (flags.translateFront) {
camera.rotateDown(Math.PI / 3600000 * setStep)
}
// 相机向后平移
if (flags.translateBehind) {
camera.rotateUp(Math.PI / 3600000 * setStep)
}
});
return m;
}
// 相机翻滚角设置方法
hprSetting(h, p, r) {
viewer.camera.setView({
orientation: {
heading: heading + h,
pitch: pitch + p,
roll: roll + r,
},
});
}
// 监听键盘按下和松开的状态
getFlagFromKeyboard(k) {
switch (k.key) {
// 按字符的Unicode编码
// 相机姿态
case "ArrowUp":
return "picthUp";
case "ArrowDown":
return "picthDown";
case "ArrowLeft":
return "headingLeft";
case "ArrowRight":
return "headingRight";
case "j":
return "rollRight";
case "l":
return "rollLeft";
// 相机向屏幕中心点前进后退
case "i":
return "moveForward";
case "k":
return "moveBackward";
// 相机前后左右上下平移
case "w":
return "translateFront";
case "s":
return "translateBehind";
case "a":
return "moveLeft";
case "d":
return "moveRight";
case "q":
return "moveUp";
case "e":
return "moveDown";
default:
return undefined;
}
}
/**
* 销毁键盘漫游事件
*/
quit() {
document.removeEventListener("keydown", this.down, false);
document.removeEventListener("keyup", this.up, false);
viewer.clock.onTick.removeEventListener(funcTick);
// 解除禁用鼠标移动地图事件
viewer.scene.screenSpaceCameraController.enableTranslate = true;
// 解除视图锁定事件。
viewer.scene.screenSpaceCameraController.enableTilt = true;
}
}
export default keyboardRoam;