diff --git a/src/App.vue b/src/App.vue index 75d28a8..3258cbe 100644 --- a/src/App.vue +++ b/src/App.vue @@ -9,6 +9,99 @@ import * as egm96 from 'egm96-universal' const store = useStore() const isDraggingSlider = ref(false) const isMinimapExpanded = ref(false) +const canCreateWayline = ref(false) + +// 导出航线 +function exportWayline() { + if (window.wayline) { + const json = window.wayline.exportToJson() + const blob = new Blob([json], { type: 'application/json' }) + const url = URL.createObjectURL(blob) + const a = document.createElement('a') + a.href = url + a.download = `wayline_${new Date().toISOString().slice(0, 19).replace(/[-:]/g, '')}.json` + document.body.appendChild(a) + a.click() + document.body.removeChild(a) + URL.revokeObjectURL(url) + } +} + +// 导入航线 +function importWayline() { + const input = document.createElement('input') + input.type = 'file' + input.accept = '.json' + input.onchange = (e) => { + const target = e.target as HTMLInputElement + if (target.files && target.files[0]) { + const file = target.files[0] + const reader = new FileReader() + reader.onload = (event) => { + try { + const json = event.target?.result as string + if (window.wayline) { + window.wayline.destroy() + } + window.wayline = Wayline.importFromJson(json, false) + } catch (error) { + console.error('Failed to import wayline:', error) + alert('导入航线失败,请检查文件格式') + } + } + reader.readAsText(file) + } + } + input.click() +} + +// 开始创建航线 +function startCreateWayline() { + canCreateWayline.value = true + // 更改光标样式 + viewer.scene.canvas.style.cursor = 'crosshair' +} + +// 结束创建航线 +function endCreateWayline() { + canCreateWayline.value = false + // 恢复默认光标 + viewer.scene.canvas.style.cursor = 'default' +} + +// 保存航点状态 +function saveWaypointState() { + if (window.wayline && window.wayline.selectedWaypoint) { + const selectedWaypoint = window.wayline.selectedWaypoint + const minimapViewer = window.wayline.minimapViewer + + // 同步偏航角和云台状态 + selectedWaypoint.orientation = { + heading: minimapViewer.camera.heading, + pitch: minimapViewer.camera.pitch, + roll: minimapViewer.camera.roll + } + + // 同步视锥体状态(FOV) + selectedWaypoint.fov = minimapViewer.camera.frustum.fov + + // 同步高度信息 + const cartographic = Cartographic.fromCartesian(selectedWaypoint.position) + selectedWaypoint.alt = cartographic.height + const height = egm96.meanSeaLevel( + cesiumMath.toDegrees(cartographic.latitude), + cesiumMath.toDegrees(cartographic.longitude) + ) + selectedWaypoint.asl = selectedWaypoint.alt - height + + // 更新航点选择状态,触发UI更新 + selectedWaypoint.unselect() + selectedWaypoint.select() + + // 同步到store + window.wayline.syncPointListToStore() + } +} // 声明全局变量类型 declare global { @@ -151,6 +244,8 @@ onMounted(async () => { const scene = viewer.scene const handler = new ScreenSpaceEventHandler(scene.canvas) handler.setInputAction(async function (click: ScreenSpaceEventHandler.PositionedEvent) { + if (!canCreateWayline.value) return + const ray = scene.camera.getPickRay(click.position) if (!ray) { @@ -159,15 +254,20 @@ onMounted(async () => { const cartesian = scene.globe.pick(ray, scene) if (defined(cartesian)) { + // 恢复默认光标 viewer.scene.canvas.style.cursor = 'default' + canCreateWayline.value = false const cartographic = Cartographic.fromCartesian(cartesian) const height = egm96.meanSeaLevel(cesiumMath.toDegrees(cartographic.latitude), cesiumMath.toDegrees(cartographic.longitude)) const terrainPosition = await getTerrainPosition(cartographic) - window.wayline = new Wayline(terrainPosition) + // 直接创建Wayline实例,第一个创建的点就是航点 + window.wayline = new Wayline() + // 将点击位置作为第一个航点 + window.wayline.createWayPoint(terrainPosition) - handler.removeInputAction(ScreenSpaceEventType.LEFT_CLICK) + // 不移除点击事件,因为用户可能需要创建多个航线 } }, ScreenSpaceEventType.LEFT_CLICK) @@ -256,7 +356,7 @@ async function getTerrainPosition(cartographic: Cartographic) {