diff --git a/packages/screen/src/views/3DSituationalAwarenessRefactor/assets/images/区县应急点.png b/packages/screen/src/views/3DSituationalAwarenessRefactor/assets/images/区县应急点.png
index a3e7adc..38b8450 100644
Binary files a/packages/screen/src/views/3DSituationalAwarenessRefactor/assets/images/区县应急点.png and b/packages/screen/src/views/3DSituationalAwarenessRefactor/assets/images/区县应急点.png differ
diff --git a/packages/screen/src/views/3DSituationalAwarenessRefactor/assets/images/市应急点.png b/packages/screen/src/views/3DSituationalAwarenessRefactor/assets/images/市应急点.png
index 5de08c3..bc2dd15 100644
Binary files a/packages/screen/src/views/3DSituationalAwarenessRefactor/assets/images/市应急点.png and b/packages/screen/src/views/3DSituationalAwarenessRefactor/assets/images/市应急点.png differ
diff --git a/packages/screen/src/views/3DSituationalAwarenessRefactor/components/LeftPanel/ForceDispatch.vue b/packages/screen/src/views/3DSituationalAwarenessRefactor/components/LeftPanel/ForceDispatch.vue
index 8be8dab..12740de 100644
--- a/packages/screen/src/views/3DSituationalAwarenessRefactor/components/LeftPanel/ForceDispatch.vue
+++ b/packages/screen/src/views/3DSituationalAwarenessRefactor/components/LeftPanel/ForceDispatch.vue
@@ -108,7 +108,7 @@ const emit = defineEmits(['view-plan', 'start-dispatch'])
*/
const getLevelText = (level) => {
const item = RESPONSE_LEVELS.find(l => l.value === level)
- return item ? `${item.label}` : '三级'
+ return item ? `${item.label}` : '四级'
}
/**
diff --git a/packages/screen/src/views/3DSituationalAwarenessRefactor/components/LeftPanel/ForcePreset.vue b/packages/screen/src/views/3DSituationalAwarenessRefactor/components/LeftPanel/ForcePreset.vue
index 08a8370..98643f9 100644
--- a/packages/screen/src/views/3DSituationalAwarenessRefactor/components/LeftPanel/ForcePreset.vue
+++ b/packages/screen/src/views/3DSituationalAwarenessRefactor/components/LeftPanel/ForcePreset.vue
@@ -5,7 +5,7 @@
距离灾害点{{ forcePreset.searchRadius }}km范围内距离灾害点{{ forcePreset.searchRadius - 20 }}km范围内
应急基地与预置点
{
+ console.log('viewer',viewer.value);
+ console.log('triggerJump',triggerJump);
+
+
+ if (viewer.value && triggerJump) {
+
+ triggerJump(5, 10) // 触发5秒跳动,高度10像素
+ }
+}
+
// 下拉框状态
const isDropdownOpen = ref(false);
// 距离选项
const distanceOptions = [
// { value: 10, label: "距离灾害点10km范围内" },
- { value: 30, label: "距离灾害点30km范围内" },
- { value: 50, label: "距离灾害点50km范围内" },
+ { value: 30, label: "距离灾害点10km范围内" },
+ { value: 50, label: "距离灾害点30km范围内" },
];
/**
diff --git a/packages/screen/src/views/3DSituationalAwarenessRefactor/components/RightPanel/CollaborationInfo.vue b/packages/screen/src/views/3DSituationalAwarenessRefactor/components/RightPanel/CollaborationInfo.vue
index baa9bbe..6fa052a 100644
--- a/packages/screen/src/views/3DSituationalAwarenessRefactor/components/RightPanel/CollaborationInfo.vue
+++ b/packages/screen/src/views/3DSituationalAwarenessRefactor/components/RightPanel/CollaborationInfo.vue
@@ -18,7 +18,8 @@
[{{ info.source }}]
+ >[{{ info.source }}]
{{ info.content }}
@@ -26,55 +27,61 @@
diff --git a/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useDisasterData.js b/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useDisasterData.js
index f58ffce..61c4daa 100644
--- a/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useDisasterData.js
+++ b/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useDisasterData.js
@@ -7,11 +7,11 @@ export function useDisasterData() {
// 灾害基本信息
const disasterInfo = ref({
type: '边坡垮塌',
- volume: '10022',
+ volume: '1220',
volumeUnit: 'm³',
- length: '13',
+ length: '33',
lengthUnit: 'm',
- width: '5',
+ width: '15',
widthUnit: 'm',
casualties: '0',
vehicles: '0',
@@ -43,7 +43,7 @@ export function useDisasterData() {
// 力量调度信息
const forceDispatch = ref({
- responseLevel: 3, // 三级
+ responseLevel: 4, // 四级
estimatedClearTime: getCurrentDateTime('24:00'),
plan: {
name: '智能应急方案',
diff --git a/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useDualMapCompare.js b/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useDualMapCompare.js
index 4b0c6ce..e0222e2 100644
--- a/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useDualMapCompare.js
+++ b/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useDualMapCompare.js
@@ -1,6 +1,7 @@
import { ref, onUnmounted } from 'vue'
import * as Cesium from 'cesium'
import { use3DTiles } from './use3DTiles'
+import { useMapMarkers } from '../composables/useMapMarkers'
/**
* 双地图对比模式
@@ -29,6 +30,8 @@ export function useDualMapCompare() {
const { load3DTileset } = use3DTiles()
+ const { drawCollapseBoundaryLeft } = useMapMarkers()
+
/**
* 初始化左侧Viewer(灾前场景)
* @param {HTMLElement} container - 容器元素
@@ -183,7 +186,7 @@ export function useDualMapCompare() {
Cesium.Cartesian3.clone(currentPosition, syncController._lastPosition)
} else {
const positionChanged = !Cesium.Cartesian3.equalsEpsilon(
- currentPosition,
+ currentPosition,
syncController._lastPosition,
0.1
)
@@ -192,7 +195,7 @@ export function useDualMapCompare() {
handleCameraSync()
}
if (!controller.isMoving) {
- syncController._isUserInteracting = false
+ syncController._isUserInteracting = false
}
Cesium.Cartesian3.clone(currentPosition, syncController._lastPosition)
}
@@ -502,6 +505,13 @@ export function useDualMapCompare() {
}
await enableCompareMode(rightViewerInstance, options)
+ const leftContainer = document.getElementById('leftCesiumContainer')
+ if (leftContainer) {
+ console.log('[index.vue] 绘制左侧坍塌边界红色虚线...')
+ drawCollapseBoundaryLeft(leftContainer)
+
+ console.log('[index.vue] 左侧坍塌边界红色虚线已添加')
+ }
} else {
disableCompareMode()
}
diff --git a/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useMapMarkers.js b/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useMapMarkers.js
index a17cd28..b2b90ea 100644
--- a/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useMapMarkers.js
+++ b/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useMapMarkers.js
@@ -107,11 +107,12 @@ export function useMapMarkers() {
const resolveBillboardHeightReference = (samplingSucceeded) => {
// 统一使用 CLAMP_TO_GROUND 让 Cesium 自动贴地
// 配合禁用的 3D Tiles 动态细化,标记位置会保持稳定
- return Cesium.HeightReference.CLAMP_TO_GROUND
+ // return Cesium.HeightReference.CLAMP_TO_GROUND
+ return Cesium.HeightReference.RELATIVE_TO_GROUND
}
/**
- * 绘制坍塌边界蓝色实线(右侧地图)
+ * 绘制坍塌边界红色实线(右侧地图)
* 在右侧地图上显示灾后坍塌的边界轮廓
* @param {Cesium.Viewer} viewer
* @returns {Cesium.Entity | null} 返回创建的边界线实体
@@ -143,12 +144,12 @@ export function useMapMarkers() {
console.log('[useMapMarkers] 右侧坍塌边界点位数量:', positions.length)
- // 创建蓝色实线边界
+ // 创建红色实线边界
const boundaryEntity = viewer.entities.add({
polyline: {
positions: positions,
width: 4, // 增加线宽,更明显
- material: Cesium.Color.fromCssColorString('#1CA1FF').withAlpha(1.0), // 纯蓝色实线
+ material: Cesium.Color.fromCssColorString('#FF0000').withAlpha(1.0), // 纯红色实线
clampToGround: true,
classificationType: Cesium.ClassificationType.BOTH, // 同时分类到地形和3D Tiles
zIndex: 1 // 提高层级
@@ -161,7 +162,7 @@ export function useMapMarkers() {
})
collapseBoundaryEntity.value = boundaryEntity
- console.log('[useMapMarkers] 右侧坍塌边界蓝色实线绘制完成, entityId:', boundaryEntity.id)
+ console.log('[useMapMarkers] 右侧坍塌边界红色实线绘制完成, entityId:', boundaryEntity.id)
// 强制渲染场景
viewer.scene.requestRender()
@@ -215,7 +216,7 @@ export function useMapMarkers() {
positions: positions,
width: 4,
material: new Cesium.PolylineDashMaterialProperty({
- color: Cesium.Color.fromCssColorString('#1CA1FF').withAlpha(1.0), // 蓝色
+ color: Cesium.Color.fromCssColorString('#FF0000').withAlpha(1.0), // 红色
dashLength: 16.0, // 虚线段长度
dashPattern: 255.0 // 虚线模式
}),
@@ -578,19 +579,18 @@ export function useMapMarkers() {
},
properties: isSoldier
? {
- type: 'soldier',
- name: soldierNames[Math.floor(Math.random() * soldierNames.length)],
- department: soldierDepartments[Math.floor(Math.random() * soldierDepartments.length)],
- location: `目前为止距离现场${locationDistance}公里`
- }
+ type: 'soldier',
+ name: soldierNames[Math.floor(Math.random() * soldierNames.length)],
+ department: soldierDepartments[Math.floor(Math.random() * soldierDepartments.length)],
+ location: `目前为止距离现场${locationDistance}公里`
+ }
: {
- type: 'device',
- name: deviceNames[Math.floor(Math.random() * deviceNames.length)],
- deviceType: deviceTypes[Math.floor(Math.random() * deviceTypes.length)],
- location: `目前为止距离现场${locationDistance}公里`
- }
+ type: 'device',
+ name: deviceNames[Math.floor(Math.random() * deviceNames.length)],
+ deviceType: deviceTypes[Math.floor(Math.random() * deviceTypes.length)],
+ location: `目前为止距离现场${locationDistance}公里`
+ }
})
-
entities.push(entity)
}
@@ -849,6 +849,7 @@ export function useMapMarkers() {
icon = otherEmergencyIcon
type = 'other'
levelName = '其他'
+ // return;
}
console.log(`[useMapMarkers] 添加标记: ${item.gl1Yjllmc}, 级别: ${levelString} (${levelName})`)
@@ -857,7 +858,7 @@ export function useMapMarkers() {
position: result.position,
billboard: {
image: icon,
- width: 29,
+ width: 32,
height: 32,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
heightReference: resolveBillboardHeightReference(result.samplingSucceeded),
@@ -972,6 +973,96 @@ export function useMapMarkers() {
}
}
+
+ /**
+* 触发实体像素级跳动动画
+* @param {Cesium.Viewer} viewer
+* @param {number} duration 动画持续时间(秒)
+* @param {number} pixelJumpHeight 像素跳动高度
+*/
+ const triggerJumpAnimation = (viewer, duration = 5, pixelJumpHeight = 30) => {
+ console.log(`[useMapMarkers] 触发像素跳动动画,持续时间 ${duration} 秒,像素高度 ${pixelJumpHeight}`)
+ if (!viewer) {
+ console.warn('[useMapMarkers] triggerJumpAnimation: viewer 为空')
+ return
+ }
+
+ // 收集所有需要动画的实体(包含所有类型)
+ const allEntities = [
+ ...markerEntities.value,
+ ...emergencyResourceEntities.value,
+ ...reserveCenterEntities.value
+ ].filter(e => e.billboard) // 只需要有billboard的实体
+
+ // 存储原始像素偏移量
+ const entitiesData = allEntities.map(entity => ({
+ entity,
+ originalOffset: entity.billboard.pixelOffset
+ ? new Cesium.Cartesian2(
+ entity.billboard.pixelOffset.x,
+ entity.billboard.pixelOffset.y
+ )
+ : new Cesium.Cartesian2(0, 0)
+ }))
+
+ // 动画参数
+ const startTime = Date.now()
+ const jumpDuration = 800 // 单次跳动周期(毫秒)
+ let animationActive = true
+
+ // 定义动画函数
+ const animate = () => {
+ if (!animationActive) return
+
+ const elapsed = Date.now() - startTime
+ const progress = (elapsed % jumpDuration) / jumpDuration
+
+ // 使用正弦波计算当前像素偏移
+ const currentOffset = Math.sin(progress * Math.PI * 2) * pixelJumpHeight
+
+ // 应用像素偏移到所有实体
+ entitiesData.forEach(({ entity, originalOffset }) => {
+ try {
+ entity.billboard.pixelOffset = new Cesium.Cartesian2(
+ originalOffset.x,
+ originalOffset.y - currentOffset // Y轴负方向为上移
+ )
+ } catch (error) {
+ console.warn('[useMapMarkers] 更新实体像素偏移失败:', error)
+ }
+ })
+
+ // 继续动画直到持续时间结束
+ if (elapsed < duration * 1000) {
+ requestAnimationFrame(animate)
+ } else {
+ // 恢复原始像素偏移
+ entitiesData.forEach(({ entity, originalOffset }) => {
+ entity.billboard.pixelOffset = originalOffset
+ })
+ animationActive = false
+ console.log('[useMapMarkers] 像素跳动动画结束')
+ }
+ }
+
+ // 启动动画
+ animate()
+
+ // 提供手动停止方法
+ return () => {
+ if (animationActive) {
+ animationActive = false
+ entitiesData.forEach(({ entity, originalOffset }) => {
+ entity.billboard.pixelOffset = originalOffset
+ })
+ console.log('[useMapMarkers] 像素跳动动画已手动停止')
+ }
+ }
+ }
+
+
+
+
return {
collapseAreaEntities,
markerEntities,
@@ -996,7 +1087,8 @@ export function useMapMarkers() {
clearEmergencyResourceMarkers,
addReserveCenterMarkers,
clearReserveCenterMarkers,
- getCollapseCenter: calculateCollapseCenter // 提前获取中心点,不依赖标记初始化
+ getCollapseCenter: calculateCollapseCenter, // 提前获取中心点,不依赖标记初始化
+ triggerJumpAnimation,
}
}
diff --git a/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useRangeCircle.js b/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useRangeCircle.js
index ec08b24..b1b76e9 100644
--- a/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useRangeCircle.js
+++ b/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useRangeCircle.js
@@ -64,6 +64,20 @@ export function useRangeCircle() {
outlineWidth: style.outlineWidth,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
},
+ label: {
+ text: `${radiusKm.toFixed(1) - 20} km`, // 实际是30 / 50 km 临时修改减少20km 后续调整
+ font: 'bold 24px sans-serif',
+ fillColor: Cesium.Color.WHITE,
+ outlineColor: Cesium.Color.BLACK,
+ outlineWidth: 2,
+ style: Cesium.LabelStyle.FILL_AND_OUTLINE,
+ verticalOrigin: Cesium.VerticalOrigin.CENTER,
+ horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
+ pixelOffset: new Cesium.Cartesian2(0, 0),
+ backgroundColor: Cesium.Color.fromCssColorString('#333').withAlpha(0.7),
+ backgroundPadding: new Cesium.Cartesian2(18, 12),
+ showBackground: true
+ }
})
// 禁用范围圈的鼠标交互,让点击可以穿透到下面的标记点
diff --git a/packages/screen/src/views/3DSituationalAwarenessRefactor/index.vue b/packages/screen/src/views/3DSituationalAwarenessRefactor/index.vue
index e9a6ba0..9c5ea7f 100644
--- a/packages/screen/src/views/3DSituationalAwarenessRefactor/index.vue
+++ b/packages/screen/src/views/3DSituationalAwarenessRefactor/index.vue
@@ -44,10 +44,7 @@
/>
-
+
@@ -100,7 +97,9 @@
:aria-label="isRightPanelCollapsed ? '展开右侧面板' : '收起右侧面板'"
>