初始化
This commit is contained in:
12
index.html
Normal file
12
index.html
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Cesium Vue3 项目</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script type="module" src="/src/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
1917
package-lock.json
generated
Normal file
1917
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
30
package.json
Normal file
30
package.json
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"name": "cesium-vue3-project",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "A Vue3 project integrated with Cesium for 3D geospatial visualization",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "vite build",
|
||||||
|
"preview": "vite preview",
|
||||||
|
"serve": "vite preview"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"vue": "^3.4.0",
|
||||||
|
"cesium": "^1.111.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@vitejs/plugin-vue": "^4.5.0",
|
||||||
|
"vite": "^5.0.0",
|
||||||
|
"vite-plugin-cesium": "^1.2.22"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"vue3",
|
||||||
|
"cesium",
|
||||||
|
"3d",
|
||||||
|
"geospatial",
|
||||||
|
"visualization"
|
||||||
|
],
|
||||||
|
"author": "",
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
||||||
1047
src/App.vue
Normal file
1047
src/App.vue
Normal file
File diff suppressed because it is too large
Load Diff
247
src/cameraController.js
Normal file
247
src/cameraController.js
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
import * as Cesium from 'cesium'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cesium相机控制器类
|
||||||
|
* 支持WASD键控制相机的上下左右移动
|
||||||
|
* 支持灵敏度调节(0.2-2.5)
|
||||||
|
*/
|
||||||
|
class CameraController {
|
||||||
|
constructor(viewer, options = {}) {
|
||||||
|
this.viewer = viewer
|
||||||
|
this.camera = viewer.camera
|
||||||
|
this.scene = viewer.scene
|
||||||
|
|
||||||
|
// 默认配置
|
||||||
|
this.config = {
|
||||||
|
sensitivity: options.sensitivity || 0.005, // 灵敏度,范围0.001-0.1
|
||||||
|
moveSpeed: options.moveSpeed || 100, // 基础移动速度
|
||||||
|
enabled: options.enabled !== false, // 是否启用控制器
|
||||||
|
...options
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按键状态
|
||||||
|
this.keys = {
|
||||||
|
w: false, // 向上
|
||||||
|
s: false, // 向下
|
||||||
|
a: false, // 向左
|
||||||
|
d: false // 向右
|
||||||
|
}
|
||||||
|
|
||||||
|
// 动画帧ID
|
||||||
|
this.animationFrameId = null
|
||||||
|
|
||||||
|
// 绑定事件处理函数
|
||||||
|
this.handleKeyDown = this.handleKeyDown.bind(this)
|
||||||
|
this.handleKeyUp = this.handleKeyUp.bind(this)
|
||||||
|
this.updateCamera = this.updateCamera.bind(this)
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
this.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化控制器
|
||||||
|
*/
|
||||||
|
init() {
|
||||||
|
if (this.config.enabled) {
|
||||||
|
this.enable()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用相机控制
|
||||||
|
*/
|
||||||
|
enable() {
|
||||||
|
this.config.enabled = true
|
||||||
|
document.addEventListener('keydown', this.handleKeyDown)
|
||||||
|
document.addEventListener('keyup', this.handleKeyUp)
|
||||||
|
this.startAnimation()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁用相机控制
|
||||||
|
*/
|
||||||
|
disable() {
|
||||||
|
this.config.enabled = false
|
||||||
|
document.removeEventListener('keydown', this.handleKeyDown)
|
||||||
|
document.removeEventListener('keyup', this.handleKeyUp)
|
||||||
|
this.stopAnimation()
|
||||||
|
// 重置按键状态
|
||||||
|
this.keys = { w: false, s: false, a: false, d: false }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置灵敏度
|
||||||
|
* @param {number} sensitivity - 灵敏度值,范围0.001-0.1
|
||||||
|
*/
|
||||||
|
setSensitivity(sensitivity) {
|
||||||
|
this.config.sensitivity = Math.max(0.001, Math.min(0.1, sensitivity))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前灵敏度
|
||||||
|
* @returns {number} 当前灵敏度值
|
||||||
|
*/
|
||||||
|
getSensitivity() {
|
||||||
|
return this.config.sensitivity
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置移动速度
|
||||||
|
* @param {number} speed - 基础移动速度
|
||||||
|
*/
|
||||||
|
setMoveSpeed(speed) {
|
||||||
|
this.config.moveSpeed = Math.max(1, speed)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 键盘按下事件处理
|
||||||
|
* @param {KeyboardEvent} event - 键盘事件
|
||||||
|
*/
|
||||||
|
handleKeyDown(event) {
|
||||||
|
if (!this.config.enabled) return
|
||||||
|
|
||||||
|
const key = event.key.toLowerCase()
|
||||||
|
if (key in this.keys) {
|
||||||
|
this.keys[key] = true
|
||||||
|
event.preventDefault()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 键盘释放事件处理
|
||||||
|
* @param {KeyboardEvent} event - 键盘事件
|
||||||
|
*/
|
||||||
|
handleKeyUp(event) {
|
||||||
|
if (!this.config.enabled) return
|
||||||
|
|
||||||
|
const key = event.key.toLowerCase()
|
||||||
|
if (key in this.keys) {
|
||||||
|
this.keys[key] = false
|
||||||
|
event.preventDefault()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始动画循环
|
||||||
|
*/
|
||||||
|
startAnimation() {
|
||||||
|
if (this.animationFrameId) {
|
||||||
|
cancelAnimationFrame(this.animationFrameId)
|
||||||
|
}
|
||||||
|
this.updateCamera()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 停止动画循环
|
||||||
|
*/
|
||||||
|
stopAnimation() {
|
||||||
|
if (this.animationFrameId) {
|
||||||
|
cancelAnimationFrame(this.animationFrameId)
|
||||||
|
this.animationFrameId = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新相机位置
|
||||||
|
*/
|
||||||
|
updateCamera() {
|
||||||
|
if (!this.config.enabled) return
|
||||||
|
|
||||||
|
// 检查是否有按键被按下
|
||||||
|
const hasMovement = Object.values(this.keys).some(pressed => pressed)
|
||||||
|
|
||||||
|
if (hasMovement) {
|
||||||
|
// 获取相机的当前方向向量
|
||||||
|
const camera = this.camera
|
||||||
|
const right = camera.right.clone()
|
||||||
|
const up = camera.up.clone()
|
||||||
|
|
||||||
|
// 计算移动向量
|
||||||
|
let moveVector = new Cesium.Cartesian3(0, 0, 0)
|
||||||
|
|
||||||
|
// 上下移动 (W/S)
|
||||||
|
if (this.keys.w) {
|
||||||
|
moveVector = Cesium.Cartesian3.add(moveVector, up, moveVector)
|
||||||
|
}
|
||||||
|
if (this.keys.s) {
|
||||||
|
const down = Cesium.Cartesian3.negate(up, new Cesium.Cartesian3())
|
||||||
|
moveVector = Cesium.Cartesian3.add(moveVector, down, moveVector)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 左右移动 (A/D)
|
||||||
|
if (this.keys.a) {
|
||||||
|
const left = Cesium.Cartesian3.negate(right, new Cesium.Cartesian3())
|
||||||
|
moveVector = Cesium.Cartesian3.add(moveVector, left, moveVector)
|
||||||
|
}
|
||||||
|
if (this.keys.d) {
|
||||||
|
moveVector = Cesium.Cartesian3.add(moveVector, right, moveVector)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 标准化移动向量
|
||||||
|
if (Cesium.Cartesian3.magnitude(moveVector) > 0) {
|
||||||
|
moveVector = Cesium.Cartesian3.normalize(moveVector, moveVector)
|
||||||
|
|
||||||
|
// 应用灵敏度和移动速度
|
||||||
|
const moveDistance = this.config.moveSpeed * this.config.sensitivity
|
||||||
|
moveVector = Cesium.Cartesian3.multiplyByScalar(moveVector, moveDistance, moveVector)
|
||||||
|
|
||||||
|
// 移动相机
|
||||||
|
camera.move(moveVector, moveDistance)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 继续动画循环
|
||||||
|
this.animationFrameId = requestAnimationFrame(this.updateCamera)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 销毁控制器
|
||||||
|
*/
|
||||||
|
destroy() {
|
||||||
|
this.disable()
|
||||||
|
this.viewer = null
|
||||||
|
this.camera = null
|
||||||
|
this.scene = null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前配置
|
||||||
|
* @returns {Object} 当前配置对象
|
||||||
|
*/
|
||||||
|
getConfig() {
|
||||||
|
return { ...this.config }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新配置
|
||||||
|
* @param {Object} newConfig - 新的配置选项
|
||||||
|
*/
|
||||||
|
updateConfig(newConfig) {
|
||||||
|
this.config = { ...this.config, ...newConfig }
|
||||||
|
|
||||||
|
// 如果灵敏度超出范围,自动调整
|
||||||
|
if (this.config.sensitivity < 0.001) {
|
||||||
|
this.config.sensitivity = 0.001
|
||||||
|
} else if (this.config.sensitivity > 0.1) {
|
||||||
|
this.config.sensitivity = 0.1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置所有按键状态
|
||||||
|
*/
|
||||||
|
resetKeys() {
|
||||||
|
this.keys = { w: false, s: false, a: false, d: false }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查是否正在移动
|
||||||
|
* @returns {boolean} 是否有按键被按下
|
||||||
|
*/
|
||||||
|
isMoving() {
|
||||||
|
return Object.values(this.keys).some(pressed => pressed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CameraController
|
||||||
9
src/main.js
Normal file
9
src/main.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { createApp } from 'vue'
|
||||||
|
import App from './App.vue'
|
||||||
|
import './style.css'
|
||||||
|
|
||||||
|
// 创建Vue应用实例
|
||||||
|
const app = createApp(App)
|
||||||
|
|
||||||
|
// 挂载应用
|
||||||
|
app.mount('#app')
|
||||||
81
src/style.css
Normal file
81
src/style.css
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
/* 全局样式重置 */
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||||
|
background-color: #1a1a1a;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cesium容器样式 */
|
||||||
|
.cesium-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 工具栏样式 */
|
||||||
|
.toolbar {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
left: 10px;
|
||||||
|
z-index: 1000;
|
||||||
|
background: rgba(42, 42, 42, 0.8);
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar button {
|
||||||
|
background: #48b884;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
padding: 8px 16px;
|
||||||
|
margin: 0 5px;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 14px;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar button:hover {
|
||||||
|
background: #369870;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 信息面板样式 */
|
||||||
|
.info-panel {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
right: 10px;
|
||||||
|
z-index: 1000;
|
||||||
|
background: rgba(42, 42, 42, 0.9);
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 8px;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
min-width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-panel h3 {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
color: #48b884;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-panel p {
|
||||||
|
margin: 5px 0;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
28
vite.config.js
Normal file
28
vite.config.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { defineConfig } from 'vite'
|
||||||
|
import vue from '@vitejs/plugin-vue'
|
||||||
|
import cesium from 'vite-plugin-cesium'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [
|
||||||
|
vue(),
|
||||||
|
cesium()
|
||||||
|
],
|
||||||
|
server: {
|
||||||
|
port: 3001,
|
||||||
|
open: true
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
outDir: 'dist',
|
||||||
|
sourcemap: false,
|
||||||
|
rollupOptions: {
|
||||||
|
output: {
|
||||||
|
manualChunks: {
|
||||||
|
cesium: ['cesium']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
define: {
|
||||||
|
CESIUM_BASE_URL: JSON.stringify('/cesium/')
|
||||||
|
}
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user