<template>
<div id="cesiumContainer"></div>
</template>
<script setup>
import { onMounted, reactive, ref, onBeforeUnmount } from 'vue';
import * as Cesium from 'cesium';
let viewer, scene, canvas;
onMounted(() => {
// cesium 初始化
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI0ZDJiYWZjNy01YWIzLTQ5MDQtOWRjMC1lNzRjMzZlNDkxZjgiLCJpZCI6MTYzNzI4LCJpYXQiOjE2OTM0NzM4NTZ9.TZLI1V4-2pYZoVSbt-zOkV7Yx7elhjAsqfFt5h4Nrlk';
//加载影像图层
const esri = new Cesium.ArcGisMapServerImageryProvider({
url: "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer",
enablePickFeatures: false,
layer: "img",
style: "default",
tileMatrixSetID: "w",
format: "tiles",
maximumLevel: 18,
});
window.viewer = viewer = new Cesium.Viewer('cesiumContainer', {
terrainProvider: Cesium.createWorldTerrain({
requestVertexNormals: true,
requestWaterMask: true
}),
imageryProvider: esri,
shouldAnimate: true, //是否允许动画
selectionIndicator: false,
baseLayerPicker: false,
fullscreenButton: false,
geocoder: false,
homeButton: false,
infoBox: false,
sceneModePicker: false,
timeline: false,
navigationHelpButton: false,
navigationInstructionsInitiallyVisible: false,
showRenderLoopErrors: false,
shadows: false,
});
// 显示帧率
viewer.scene.debugShowFramesPerSecond = true;
viewer._cesiumWidget._creditContainer.style.display = "none"; //去除版权信息
viewer.scene.globe.depthTestAgainstTerrain = true;
scene = viewer.scene;
canvas = viewer.canvas;//获取画布。
canvas.setAttribute("tabindex", "0");
canvas.onclick = function () {
canvas.focus();
};
const ellipsoid = scene.globe.ellipsoid;//获取描述地球形状的椭球体。
scene.screenSpaceCameraController.enableRotate = false;//如果为 true,则允许用户旋转转换用户位置的世界
scene.screenSpaceCameraController.enableTranslate = true;//如果为 true,则允许用户在地图上平移。如果为 false,则相机保持锁定在当前位置
scene.screenSpaceCameraController.enableZoom = true;//如果为true,则允许用户放大和缩小。如果为 false,则相机将锁定到与椭球的当前距离。
scene.screenSpaceCameraController.enableTilt = true;//如果为真,则允许用户倾斜相机。如果为 false,则摄像机锁定到当前航向
scene.screenSpaceCameraController.enableLook = true;//如果为 true,则允许用户使用 free-look。如果为 false,则只能通过平移或旋转来改变摄像机视图方向
let startMousePosition; // 保存鼠标初始位置
let mousePosition; // 保存鼠标当前位置
const flags = { // 一组标志,用于表示不同的操作状态
looking: false, // 表示是否正在观察/旋转相机
moveForward: false, // 向前移动
moveBackward: false, // 向后移动
moveUp: false, // 上移
moveDown: false, // 下移
moveLeft: false, // 左移
moveRight: false // 右移
};
const handler = new Cesium.ScreenSpaceEventHandler(canvas); // 创建一个交互事件处理器
handler.setInputAction(function (movement) { // 给事件处理器设置一个鼠标左键按下时的处理函数
flags.looking = true; // 将标志位 flags.looking 设置为 true,表示正在观察/旋转相机
mousePosition = startMousePosition = Cesium.Cartesian3.clone(movement.position); // 保存鼠标初始位置
}, Cesium.ScreenSpaceEventType.LEFT_DOWN); // 当鼠标左键按下时触发事件
handler.setInputAction(function (movement) { // 当鼠标移动时,更新鼠标当前位置
mousePosition = movement.endPosition;
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
handler.setInputAction(function (position) { // 当鼠标左键释放时,表示停止观察/旋转相机
flags.looking = false;
}, Cesium.ScreenSpaceEventType.LEFT_UP);
function getFlagForKeyCode(keyCode) { // 定义函数 getFlagForKeyCode,接收一个键盘按键的 keyCode 参数,返回相应的标志名称
switch (keyCode) { // 使用 switch 语句对 keyCode 进行匹配
case "W".charCodeAt(0): // 如果 keyCode 与字符 "W" 的 ASCII 码相等
return "moveForward"; // 返回 "moveForward"
case "S".charCodeAt(0): // 如果 keyCode 与字符 "S" 的 ASCII 码相等
return "moveBackward"; // 返回 "moveBackward"
case "Q".charCodeAt(0): // 如果 keyCode 与字符 "Q" 的 ASCII 码相等
return "moveUp"; // 返回 "moveUp"
case "E".charCodeAt(0): // 如果 keyCode 与字符 "E" 的 ASCII 码相等
return "moveDown"; // 返回 "moveDown"
case "D".charCodeAt(0): // 如果 keyCode 与字符 "D" 的 ASCII 码相等
return "moveRight"; // 返回 "moveRight"
case "A".charCodeAt(0): // 如果 keyCode 与字符 "A" 的 ASCII 码相等
return "moveLeft"; // 返回 "moveLeft"
default: // 如果未匹配上任何情况
return undefined; // 返回 undefined
}
}
document.addEventListener("keydown", function (e) { // 添加键盘按下事件监听器
const flagName = getFlagForKeyCode(e.keyCode); // 根据按下的键的 keyCode 获取相应的标志名称
if (typeof flagName !== "undefined") { // 如果获取的标志名称不是 undefined
flags[flagName] = true; // 将对应的标志设置为 true,表示按键被按下
}
}, false);
document.addEventListener("keyup", function (e) { // 添加键盘释放事件监听器
const flagName = getFlagForKeyCode(e.keyCode); // 根据释放的键的 keyCode 获取相应的标志名称
if (typeof flagName !== "undefined") { // 如果获取的标志名称不是 undefined
flags[flagName] = false; // 将对应的标志设置为 false,表示按键被释放
}
}, false);
viewer.clock.onTick.addEventListener(function (clock) { // 添加监听器,每次时钟更新时触发的事件处理函数
const camera = viewer.camera; // 获取相机对象
if (flags.looking) { // 如果正在观察/旋转相机
const width = canvas.clientWidth; // 获取画布的宽度
const height = canvas.clientHeight; // 获取画布的高度
// 计算鼠标移动的偏移量,并根据偏移量调整相机的旋转角度
const x = (mousePosition.x - startMousePosition.x) / width; // 计算鼠标在水平方向上的移动偏移量
const y = -(mousePosition.y - startMousePosition.y) / height; // 计算鼠标在垂直方向上的移动偏移量
const lookFactor = 0.05; // 设置旋转角度调整系数
camera.lookRight(x * lookFactor); // 根据水平移动偏移量调整相机的水平旋转角度
camera.lookUp(y * lookFactor); // 根据垂直移动偏移量调整相机的垂直旋转角度
}
const cameraHeight = ellipsoid.cartesianToCartographic(camera.position).height; // 获取相机到椭球表面的距离
const moveRate = cameraHeight / 100.0; // 根据相机到椭球表面的距离,计算移动速度
// 根据不同的标志位,调用相机对象的对应方法完成相机的移动操作
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);
}
});
});
</script>
<style scoped>
#cesiumContainer {
width: 100%;
height: 100%;
}
#cesiumContainer .cesium-viewer-bottom {
display: none;
}
.floorSingle {
position: absolute;
z-index: 99;
left: 0px;
top: 30px;
background-color: aliceblue;
}
</style>
cesium 键盘控制相机移动
最新推荐文章于 2024-04-01 15:15:41 发布