From 794dfadf25327ed83f87fb63bacf6d86c80563d3 Mon Sep 17 00:00:00 2001
From: 张含笑 <zhx18749296735@163.com>
Date: Tue, 27 Jan 2026 14:51:50 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'
---
applications/drone-command/src/components/map-container/device-map-container.vue | 123 +++++++++++++++++++++++++++++++++++++---
1 files changed, 113 insertions(+), 10 deletions(-)
diff --git a/applications/drone-command/src/components/map-container/device-map-container.vue b/applications/drone-command/src/components/map-container/device-map-container.vue
index a4311a4..f7fb7e9 100644
--- a/applications/drone-command/src/components/map-container/device-map-container.vue
+++ b/applications/drone-command/src/components/map-container/device-map-container.vue
@@ -119,6 +119,14 @@
let droneTrackTickHandler = null
let droneTrackStartTime = null
let droneTrackRuntime = []
+let favoritePulseRafId = null
+let favoritePulseStartAt = 0
+let favoritePulseElapsed = 0
+const favoritePulseEntities = []
+const pulseBaseColor = Cesium.Color.fromCssColorString('#FF3B30')
+const PULSE_MIN_RADIUS_M = 60
+const PULSE_MAX_RADIUS_M = 180
+const PULSE_DURATION_S = 1.6
const detailVisible = ref(true)
const clusterVisible = ref(false)
const countyCenterMap = new Map()
@@ -172,6 +180,57 @@
*/
const adminBoundaryVisible = ref(treeCheckedKeys.value.includes('admin'))
+
+const isFavorited = item => {
+ const value = item?.favorited ?? item?.isFavorite
+ return value === 1 || value === '1' || value === true
+}
+
+let pulseCanvas = null
+const getPulseCanvas = () => {
+ if (pulseCanvas) return pulseCanvas
+ const size = 256
+ const canvas = document.createElement('canvas')
+ canvas.width = size
+ canvas.height = size
+ const ctx = canvas.getContext('2d')
+ const center = size / 2
+ const radius = center - 2
+ const gradient = ctx.createRadialGradient(center, center, radius * 0.1, center, center, radius)
+ gradient.addColorStop(0, 'rgba(255,59,48,0.55)')
+ gradient.addColorStop(0.35, 'rgba(255,59,48,0.35)')
+ gradient.addColorStop(0.7, 'rgba(255,59,48,0.15)')
+ gradient.addColorStop(1, 'rgba(255,59,48,0)')
+ ctx.fillStyle = gradient
+ ctx.beginPath()
+ ctx.arc(center, center, radius, 0, Math.PI * 2)
+ ctx.fill()
+ pulseCanvas = canvas
+ return canvas
+}
+
+const createFavoritePulseEntity = (billboard) => {
+ if (!viewer || !billboard) return
+ const material = new Cesium.ImageMaterialProperty({
+ image: getPulseCanvas(),
+ transparent: true,
+ })
+ const pulse = {
+ material,
+ offset: Math.random() * PULSE_DURATION_S,
+ entity: null,
+ }
+ pulse.entity = viewer.entities.add({
+ position: new Cesium.CallbackProperty(() => billboard.position, false),
+ ellipse: {
+ semiMajorAxis: new Cesium.CallbackProperty(() => getPulseRadius(pulse), false),
+ semiMinorAxis: new Cesium.CallbackProperty(() => getPulseRadius(pulse), false),
+ material,
+ heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
+ },
+ })
+ favoritePulseEntities.push(pulse)
+}
const getDevicePosition = item => {
const longitudeRaw = item.longitude ?? item.lng ?? item.lon
@@ -311,6 +370,12 @@
}
}
+const getPulseRadius = pulse => {
+ const phase = ((favoritePulseElapsed + pulse.offset) % PULSE_DURATION_S) / PULSE_DURATION_S
+ const wave = phase < 0.5 ? phase * 2 : (1 - phase) * 2
+ return PULSE_MIN_RADIUS_M + (PULSE_MAX_RADIUS_M - PULSE_MIN_RADIUS_M) * wave
+}
+
const setDetailVisibility = visible => {
detailVisible.value = visible
if (defenseZonePrimitive) defenseZonePrimitive.show = visible
@@ -345,6 +410,11 @@
const setDroneVisibility = visible => {
if (droneTrackBillboardCollection) droneTrackBillboardCollection.show = visible
if (droneTrackPolylineCollection) droneTrackPolylineCollection.show = visible
+ if (favoritePulseEntities.length) {
+ favoritePulseEntities.forEach(pulse => {
+ if (pulse?.entity) pulse.entity.show = visible
+ })
+ }
if (!visible && selectedTargetType.value === 'drone') {
closePopup()
}
@@ -453,6 +523,7 @@
const clearDroneTrackEntities = () => {
if (!viewer) return
stopDroneTrackAnimation()
+ stopFavoritePulseAnimation()
if (droneTrackBillboardCollection) {
if (!droneTrackBillboardCollection.isDestroyed?.()) {
removeCockpitPrimitive(droneTrackBillboardCollection)
@@ -466,6 +537,12 @@
droneTrackPolylineCollection = null
}
droneTrackRuntime = []
+ if (favoritePulseEntities.length) {
+ favoritePulseEntities.forEach(pulse => {
+ if (pulse?.entity) viewer?.entities?.remove(pulse.entity)
+ })
+ favoritePulseEntities.length = 0
+ }
dronePickMap.clear()
if (selectedTargetType.value === 'drone') {
closePopup()
@@ -532,6 +609,28 @@
droneTrackTickHandler = null
}
+const startFavoritePulseAnimation = () => {
+ if (!viewer || favoritePulseRafId) return
+ favoritePulseStartAt = performance.now()
+ const tick = now => {
+ if (!viewer || viewer.isDestroyed?.() || !favoritePulseEntities.length) {
+ favoritePulseRafId = null
+ return
+ }
+ favoritePulseElapsed = (now - favoritePulseStartAt) / 1000
+ viewer.scene.requestRender()
+ favoritePulseRafId = requestAnimationFrame(tick)
+ }
+ favoritePulseRafId = requestAnimationFrame(tick)
+}
+
+const stopFavoritePulseAnimation = () => {
+ if (favoritePulseRafId) {
+ cancelAnimationFrame(favoritePulseRafId)
+ favoritePulseRafId = null
+ }
+}
+
const renderSimulatedDroneTrack = (list) => {
if (!viewer) return
clearDroneTrackEntities()
@@ -576,16 +675,19 @@
})
billboard.id = droneId
const speedMs = Math.round(Cesium.Cartesian3.distance(positions[0], positions[1]) / segmentDuration)
- dronePickMap.set(droneId, {
- data: {
- ...item,
- flightHeightM: item.flightHeightM ?? points[0].height,
- flightSpeedMs: item.flightSpeedMs ?? speedMs,
- longitude: item.longitude ?? points[0].longitude,
- latitude: item.latitude ?? points[0].latitude,
- },
- billboard,
- })
+ dronePickMap.set(droneId, {
+ data: {
+ ...item,
+ flightHeightM: item.flightHeightM ?? points[0].height,
+ flightSpeedMs: item.flightSpeedMs ?? speedMs,
+ longitude: item.longitude ?? points[0].longitude,
+ latitude: item.latitude ?? points[0].latitude,
+ },
+ billboard,
+ })
+ if (isFavorited(item)) {
+ createFavoritePulseEntity(billboard)
+ }
droneTrackRuntime.push({
positions,
billboard,
@@ -595,6 +697,7 @@
})
viewer.clock.multiplier = 1
startDroneTrackAnimation()
+ startFavoritePulseAnimation()
reorderCockpitPrimitives()
}
--
Gitblit v1.9.3