修复圆圈会重复添加的bug

This commit is contained in:
huangchenhao 2025-11-28 05:21:19 +08:00
parent 18913c6ae8
commit a9e2e836e0
5 changed files with 70 additions and 62 deletions

View File

@ -97,7 +97,8 @@
<div class="stat-card stat-card--personnel">
<span class="stat-label">应急人员</span>
<div class="stat-value-wrapper">
<span class="stat-value">{{ forcePreset.personnel }}</span>
<!-- <span class="stat-value">{{ forcePreset.personnel }}</span> -->
<span class="stat-value">{{ distance === 30 ? 47 : 69 }}</span>
<span class="stat-unit"></span>
</div>
</div>
@ -177,7 +178,9 @@ const closeDropdown = () => {
* 选择选项
* @param {number} value - 选中的距离值
*/
const distance = ref(30);
const selectOption = (value) => {
distance.value = value;
if (onDistanceChange) {
onDistanceChange(value);
}

View File

@ -994,6 +994,8 @@ export function useMapMarkers() {
...reserveCenterEntities.value
].filter(e => e.billboard) // 只需要有billboard的实体
console.log('allEntities', allEntities)
// 存储原始像素偏移量
const entitiesData = allEntities.map(entity => ({
entity,

View File

@ -3,9 +3,9 @@ import { ref } from 'vue'
import { DISASTER_CENTER, RANGE_CIRCLE_STYLE } from '../constants'
export function useRangeCircle() {
const rangeCircleEntity = ref(null)
const radiusLineEntity = ref(null) // 单独存储半径线实体
const labelEntity = ref(null) // 单独存储标签实体
const rangeCircleEntities = ref([]) // 改为数组存储所有范围圈实体
const radiusLineEntities = ref([]) // 存储所有半径线实体
const labelEntities = ref([]) // 存储所有标签实体
const createOrUpdateRangeCircle = (
viewer,
@ -25,30 +25,24 @@ export function useRangeCircle() {
const radiusMeters = radiusKm * 1000
// 如果已存在范围圈,先检查半径和中心点是否相同
if (rangeCircleEntity.value) {
// 获取现有范围圈的半径(从 semiMajorAxis 获取,单位是米,转换为公里)
const existingRadiusKm = rangeCircleEntity.value.ellipse.semiMajorAxis / 1000
// 检查是否已存在相同半径的范围圈
const existingCircleIndex = rangeCircleEntities.value.findIndex(entity => {
if (!entity) return false
const existingRadiusKm = entity.ellipse.semiMajorAxis / 1000
return existingRadiusKm === radiusKm
})
// 检查中心点是否相同
const existingPosition = rangeCircleEntity.value.position.getValue()
const newPosition = Cesium.Cartesian3.fromDegrees(centerLon, centerLat, 0)
const centerChanged = !Cesium.Cartesian3.equals(existingPosition, newPosition)
// 如果半径和中心点都相同,则不需要更新
if (existingRadiusKm === radiusKm && !centerChanged) {
console.log(`[useRangeCircle] 范围圈半径相同 (${radiusKm}km),无需更新`)
return
}
// 移除现有实体
// clearRangeCircle(viewer)
// 如果已存在相同半径的范围圈,则不需要重复创建
if (existingCircleIndex !== -1) {
showRangeCircle();
console.log(`[useRangeCircle] 已存在相同半径的范围圈 (${radiusKm}km),无需重复创建`)
return
}
// 创建中心点坐标
const centerCartesian = Cesium.Cartesian3.fromDegrees(centerLon, centerLat)
// 计算半径线终点(正东方向)- 使用您之前正确的计算方法
// 计算半径线终点(正东方向)
const ellipsoid = Cesium.Ellipsoid.WGS84
const surfaceNormal = ellipsoid.geodeticSurfaceNormal(centerCartesian, new Cesium.Cartesian3())
const tangent = Cesium.Cartesian3.cross(surfaceNormal, Cesium.Cartesian3.UNIT_Z, new Cesium.Cartesian3())
@ -56,12 +50,17 @@ export function useRangeCircle() {
Cesium.Cartesian3.multiplyByScalar(tangent, radiusMeters, tangent)
const radiusEndCartesian = Cesium.Cartesian3.add(centerCartesian, tangent, new Cesium.Cartesian3())
// 计算半径线中点
const midpointCartesian = new Cesium.Cartesian3()
Cesium.Cartesian3.lerp(centerCartesian, radiusEndCartesian, 0.5, midpointCartesian)
// 计算标签位置3/4处并向下偏移
const labelPositionCartesian = new Cesium.Cartesian3()
Cesium.Cartesian3.lerp(centerCartesian, radiusEndCartesian, 0.75, labelPositionCartesian)
// 计算向下偏移的方向(垂直于半径线方向)
const offsetDirection = Cesium.Cartesian3.cross(Cesium.Cartesian3.UNIT_Z, tangent, new Cesium.Cartesian3())
Cesium.Cartesian3.normalize(offsetDirection, offsetDirection)
Cesium.Cartesian3.multiplyByScalar(offsetDirection, - radiusMeters * 0.2, offsetDirection) // 向下偏移 20%
Cesium.Cartesian3.add(labelPositionCartesian, offsetDirection, labelPositionCartesian)
// 创建范围圈实体
rangeCircleEntity.value = viewer.entities.add({
// 创建范围圈实体并添加到数组
const circleEntity = viewer.entities.add({
position: centerCartesian,
ellipse: {
semiMinorAxis: radiusMeters,
@ -74,9 +73,10 @@ export function useRangeCircle() {
},
allowPicking: false
})
rangeCircleEntities.value.push(circleEntity)
// 创建半径线实体
radiusLineEntity.value = viewer.entities.add({
// 创建半径线实体并添加到数组
const lineEntity = viewer.entities.add({
polyline: {
positions: [centerCartesian, radiusEndCartesian],
width: 2,
@ -84,10 +84,11 @@ export function useRangeCircle() {
},
allowPicking: false
})
radiusLineEntities.value.push(lineEntity)
// 创建标签实体(单独创建,位置设为半径线中点)
labelEntity.value = viewer.entities.add({
position: midpointCartesian,
// 创建标签实体并添加到数组
const currentLabelEntity = viewer.entities.add({
position: labelPositionCartesian,
label: {
text: `${radiusKm - 20} km`,
font: 'bold 16px sans-serif',
@ -95,55 +96,55 @@ export function useRangeCircle() {
outlineColor: Cesium.Color.BLACK,
outlineWidth: 2,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
verticalOrigin: Cesium.VerticalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 调整垂直原点为底部
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
pixelOffset: new Cesium.Cartesian2(0, 0),
pixelOffset: new Cesium.Cartesian2(0, 10), // 增加像素偏移,确保标签不在半径线上
backgroundColor: Cesium.Color.fromCssColorString('#333').withAlpha(0.7),
backgroundPadding: new Cesium.Cartesian2(8, 6),
showBackground: true,
},
allowPicking: false
})
labelEntities.value.push(currentLabelEntity)
console.log(`[useRangeCircle] 已创建/更新范围圈: ${radiusKm}km`)
console.log(`[useRangeCircle] 已创建范围圈: ${radiusKm}km`)
}
// 其他函数也需要相应修改为操作数组
const showRangeCircle = () => {
if (rangeCircleEntity.value) rangeCircleEntity.value.show = true
if (radiusLineEntity.value) radiusLineEntity.value.show = true
if (labelEntity.value) labelEntity.value.show = true
rangeCircleEntities.value.forEach(entity => entity.show = true)
radiusLineEntities.value.forEach(entity => entity.show = true)
labelEntities.value.forEach(entity => entity.show = true)
}
const hideRangeCircle = () => {
if (rangeCircleEntity.value) rangeCircleEntity.value.show = false
if (radiusLineEntity.value) radiusLineEntity.value.show = false
if (labelEntity.value) labelEntity.value.show = false
rangeCircleEntities.value.forEach(entity => entity.show = false)
radiusLineEntities.value.forEach(entity => entity.show = false)
labelEntities.value.forEach(entity => entity.show = false)
}
const clearRangeCircle = (viewer) => {
if (!viewer) return
if (rangeCircleEntity.value) {
viewer.entities.remove(rangeCircleEntity.value)
rangeCircleEntity.value = null
}
if (radiusLineEntity.value) {
viewer.entities.remove(radiusLineEntity.value)
radiusLineEntity.value = null
}
if (labelEntity.value) {
viewer.entities.remove(labelEntity.value)
labelEntity.value = null
}
console.log('[useRangeCircle] 范围圈已清除')
// 清除所有实体
rangeCircleEntities.value.forEach(entity => viewer.entities.remove(entity))
radiusLineEntities.value.forEach(entity => viewer.entities.remove(entity))
labelEntities.value.forEach(entity => viewer.entities.remove(entity))
// 清空数组
rangeCircleEntities.value = []
radiusLineEntities.value = []
labelEntities.value = []
console.log('[useRangeCircle] 所有范围圈已清除')
}
return {
rangeCircleEntity,
rangeCircleEntities, // 返回数组
createOrUpdateRangeCircle,
showRangeCircle,
hideRangeCircle,
clearRangeCircle,
}
}

View File

@ -25,7 +25,7 @@ export const VIDEO_MONITORS = [
title: '单兵(张维)设备视角',
videoSrc:
'http://222.212.85.86:9000/300bdf2b-a150-406e-be63-d28bd29b409f/demo/ylzg/单兵视角.mp4',
dateRange: '2025/9/1-2025/12/1',
// dateRange: '2025/9/1-2025/12/1',
hasAudio: true,
hasMegaphone: true,
hasZoom: true,
@ -37,7 +37,7 @@ export const VIDEO_MONITORS = [
title: '无人机(001)视角',
videoSrc:
'http://222.212.85.86:9000/300bdf2b-a150-406e-be63-d28bd29b409f/demo/ylzg/无人机视角.mp4',
dateRange: '2025/9/1-2025/12/1',
// dateRange: '2025/9/1-2025/12/1',
hasAudio: false,
hasMegaphone: true,
hasZoom: true,
@ -49,7 +49,7 @@ export const VIDEO_MONITORS = [
title: '设备操作视角',
videoSrc:
'http://222.212.85.86:9000/300bdf2b-a150-406e-be63-d28bd29b409f/demo/ylzg/设备视角.mp4',
dateRange: '2025/9/1-2025/12/1',
// dateRange: '2025/9/1-2025/12/1',
hasAudio: true,
hasMegaphone: true,
hasZoom: true,
@ -61,7 +61,7 @@ export const VIDEO_MONITORS = [
title: '指挥会议室视角',
videoSrc:
'http://222.212.85.86:9000/300bdf2b-a150-406e-be63-d28bd29b409f/demo/ylzg/指挥会议室视角.mp4',
dateRange: '2025/9/1-2025/12/1',
// dateRange: '2025/9/1-2025/12/1',
hasAudio: true,
hasMegaphone: true,
hasZoom: true,

View File

@ -564,6 +564,9 @@ const handleVideoModalClose = () => {
const handleStartDispatch = async (payload) => {
console.log("[index.vue] 启动响应调度");
await createOrUpdateRangeCircle(mapStore.viewer, 30);
await createOrUpdateRangeCircle(mapStore.viewer, 50);
// Check if Quick Response has been executed
if (!quickResponseExecuted.value) {
console.log("[index.vue] 快速响应未执行,自动执行...");
@ -1461,7 +1464,6 @@ const initializeScene = async () => {
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
},
priority: 10000, //
});
console.log("[index.vue] 中心点标记已添加");