refactor(3d-situational-awareness): 增强双地图相机同步功能并加入防御性检查机制
* 引入视窗(viewer)存在性和销毁检查,以防止同步过程中发生错误。 * 引入原子停止标志(atomic stop flags)和移动结束(moveEnd)追踪,以优化控制流程。 * 提高位置变化检测的精度,并优化日志记录功能。
This commit is contained in:
parent
bb5bed014c
commit
49e963e196
@ -102,10 +102,32 @@ export function useDualMapCompare() {
|
||||
let isSyncing = false
|
||||
const handleCameraSync = () => {
|
||||
if (isSyncing) return
|
||||
|
||||
// 防御检查1:viewer 存在性检查
|
||||
if (!rightViewerInstance || !leftViewerInstance) {
|
||||
return
|
||||
}
|
||||
|
||||
// 防御检查2:viewer destroyed 状态检查
|
||||
if (rightViewerInstance.isDestroyed?.() || leftViewerInstance.isDestroyed?.()) {
|
||||
return
|
||||
}
|
||||
|
||||
isSyncing = true
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
try {
|
||||
// 再次检查(requestAnimationFrame 可能延迟执行)
|
||||
if (!rightViewerInstance || !leftViewerInstance) {
|
||||
isSyncing = false
|
||||
return
|
||||
}
|
||||
|
||||
if (rightViewerInstance.isDestroyed?.() || leftViewerInstance.isDestroyed?.()) {
|
||||
isSyncing = false
|
||||
return
|
||||
}
|
||||
|
||||
const rightCamera = rightViewerInstance.camera
|
||||
leftViewerInstance.camera.setView({
|
||||
destination: rightCamera.position.clone(),
|
||||
@ -129,8 +151,13 @@ export function useDualMapCompare() {
|
||||
_moveEndHandler: null,
|
||||
_lastPosition: null,
|
||||
_interval: null,
|
||||
_stopped: false, // 新增:原子性停止标志
|
||||
_moveEndReceived: false, // 新增:标记 moveEnd 是否已触发
|
||||
|
||||
start: () => {
|
||||
// 重置停止标志
|
||||
syncController._stopped = false
|
||||
|
||||
const controller = rightViewerInstance.scene.screenSpaceCameraController
|
||||
|
||||
if (!controller) {
|
||||
@ -142,13 +169,27 @@ export function useDualMapCompare() {
|
||||
if (typeof rightViewerInstance.camera.moveStart?.addEventListener === 'function' &&
|
||||
typeof rightViewerInstance.camera.moveEnd?.addEventListener === 'function') {
|
||||
|
||||
// 监听相机移动开始(替代所有操作类型监听)
|
||||
// 监听相机移动开始
|
||||
const moveStartHandler = rightViewerInstance.camera.moveStart.addEventListener(() => {
|
||||
if (syncController._stopped) return // 检查停止标志
|
||||
|
||||
syncController._isUserInteracting = true
|
||||
console.log('[useDualMapCompare] 捕获相机操作开始')
|
||||
|
||||
// 新增拖动持续监听
|
||||
// 改进:只在首次触发时启动递归
|
||||
const onDragFrame = () => {
|
||||
// 停止检查
|
||||
if (syncController._stopped) {
|
||||
console.log('[useDualMapCompare] 停止标志已设置,退出递归')
|
||||
return
|
||||
}
|
||||
|
||||
// viewer 有效性检查
|
||||
if (!rightViewerInstance || rightViewerInstance.isDestroyed?.()) {
|
||||
console.log('[useDualMapCompare] Viewer已销毁,退出递归')
|
||||
return
|
||||
}
|
||||
|
||||
if (syncController._isUserInteracting) {
|
||||
console.log('[useDualMapCompare] 主同步触发')
|
||||
handleCameraSync()
|
||||
@ -158,12 +199,17 @@ export function useDualMapCompare() {
|
||||
requestAnimationFrame(onDragFrame)
|
||||
})
|
||||
|
||||
// 2. 同步逻辑
|
||||
syncController._interactionHandlers.push(moveStartHandler)
|
||||
|
||||
// 2. 监听相机移动结束
|
||||
syncController._moveEndHandler = rightViewerInstance.camera.moveEnd.addEventListener(() => {
|
||||
if (syncController._stopped) return // 检查停止标志
|
||||
|
||||
if (syncController._isUserInteracting) {
|
||||
console.log('[useDualMapCompare] 主同步触发')
|
||||
handleCameraSync()
|
||||
syncController._isUserInteracting = false
|
||||
console.log('[useDualMapCompare] moveEnd 事件触发,等待相机完全停止...')
|
||||
// 不要立即重置 _isUserInteracting,让 setInterval 继续检测
|
||||
// 标记为"移动已结束但可能还在惯性滑动"
|
||||
syncController._moveEndReceived = true
|
||||
}
|
||||
})
|
||||
|
||||
@ -172,62 +218,113 @@ export function useDualMapCompare() {
|
||||
return
|
||||
}
|
||||
|
||||
// 3. 保险同步逻辑
|
||||
// 3. 保险同步逻辑(setInterval)
|
||||
syncController._lastPosition = new Cesium.Cartesian3()
|
||||
syncController._moveEndReceived = false // 重置标志
|
||||
syncController._interval = setInterval(() => {
|
||||
// 停止检查
|
||||
if (syncController._stopped) return
|
||||
|
||||
// viewer 有效性检查
|
||||
if (!rightViewerInstance || rightViewerInstance.isDestroyed?.()) {
|
||||
console.log('[useDualMapCompare] Viewer已销毁,停止定时同步')
|
||||
if (syncController._interval) {
|
||||
clearInterval(syncController._interval)
|
||||
syncController._interval = null
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const isMoving = controller.isMoving
|
||||
const currentPosition = rightViewerInstance.camera.position
|
||||
|
||||
if (syncController._isUserInteracting) {
|
||||
if (isMoving) {
|
||||
// 相机正在移动,持续更新位置
|
||||
Cesium.Cartesian3.clone(currentPosition, syncController._lastPosition)
|
||||
syncController._moveEndReceived = false // 重置标志
|
||||
} else {
|
||||
const positionChanged = !Cesium.Cartesian3.equalsEpsilon(
|
||||
currentPosition,
|
||||
syncController._lastPosition,
|
||||
0.1
|
||||
)
|
||||
if (positionChanged) {
|
||||
console.log('[useDualMapCompare] 保险同步触发')
|
||||
handleCameraSync()
|
||||
}
|
||||
if (!controller.isMoving) {
|
||||
// 相机已停止移动
|
||||
if (syncController._moveEndReceived) {
|
||||
// moveEnd 已触发且相机已停止,执行最终同步
|
||||
const positionChanged = !Cesium.Cartesian3.equalsEpsilon(
|
||||
currentPosition,
|
||||
syncController._lastPosition,
|
||||
0.001 // 更高精度
|
||||
)
|
||||
|
||||
if (positionChanged) {
|
||||
console.log('[useDualMapCompare] 相机完全停止,执行最终同步')
|
||||
handleCameraSync()
|
||||
Cesium.Cartesian3.clone(currentPosition, syncController._lastPosition)
|
||||
} else {
|
||||
console.log('[useDualMapCompare] 相机完全停止,位置无变化')
|
||||
}
|
||||
|
||||
// 重置状态
|
||||
syncController._isUserInteracting = false
|
||||
syncController._moveEndReceived = false
|
||||
} else {
|
||||
// 相机停止但 moveEnd 未触发(可能是微小移动后停止)
|
||||
const positionChanged = !Cesium.Cartesian3.equalsEpsilon(
|
||||
currentPosition,
|
||||
syncController._lastPosition,
|
||||
0.1
|
||||
)
|
||||
|
||||
if (positionChanged) {
|
||||
console.log('[useDualMapCompare] 保险同步触发(相机停止但moveEnd未触发)')
|
||||
handleCameraSync()
|
||||
Cesium.Cartesian3.clone(currentPosition, syncController._lastPosition)
|
||||
syncController._isUserInteracting = false
|
||||
}
|
||||
}
|
||||
Cesium.Cartesian3.clone(currentPosition, syncController._lastPosition)
|
||||
}
|
||||
}
|
||||
}, 300)
|
||||
|
||||
console.log('[useDualMapCompare] 智能同步设置完成')
|
||||
console.log('[useDualMapCompare] 智能同步已启动')
|
||||
},
|
||||
|
||||
stop: () => {
|
||||
const controller = rightViewerInstance.scene.screenSpaceCameraController
|
||||
// 原子性设置停止标志(最优先)
|
||||
syncController._stopped = true
|
||||
|
||||
// 移除 moveStart 监听
|
||||
syncController._interactionHandlers.forEach(handler => {
|
||||
if (typeof rightViewerInstance.camera.moveStart?.removeEventListener === 'function') {
|
||||
rightViewerInstance.camera.moveStart.removeEventListener(handler)
|
||||
}
|
||||
})
|
||||
syncController._interactionHandlers = []
|
||||
|
||||
// 移除 moveEnd 监听
|
||||
if (syncController._moveEndHandler &&
|
||||
typeof rightViewerInstance.camera.moveEnd?.removeEventListener === 'function') {
|
||||
rightViewerInstance.camera.moveEnd.removeEventListener(syncController._moveEndHandler)
|
||||
}
|
||||
|
||||
// 清除保险同步
|
||||
// 立即清除定时器
|
||||
if (syncController._interval) {
|
||||
clearInterval(syncController._interval)
|
||||
syncController._interval = null
|
||||
}
|
||||
|
||||
// 移除事件监听器(需要检查 viewer 是否仍然有效)
|
||||
if (rightViewerInstance && !rightViewerInstance.isDestroyed?.()) {
|
||||
syncController._interactionHandlers.forEach(handler => {
|
||||
if (typeof rightViewerInstance.camera.moveStart?.removeEventListener === 'function') {
|
||||
try {
|
||||
rightViewerInstance.camera.moveStart.removeEventListener(handler)
|
||||
} catch (e) {
|
||||
console.warn('[useDualMapCompare] 移除 moveStart 监听器失败:', e)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (syncController._moveEndHandler &&
|
||||
typeof rightViewerInstance.camera.moveEnd?.removeEventListener === 'function') {
|
||||
try {
|
||||
rightViewerInstance.camera.moveEnd.removeEventListener(syncController._moveEndHandler)
|
||||
} catch (e) {
|
||||
console.warn('[useDualMapCompare] 移除 moveEnd 监听器失败:', e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
syncController._interactionHandlers = []
|
||||
syncController._moveEndHandler = null
|
||||
syncController._isUserInteracting = false
|
||||
syncController._moveEndReceived = false // 重置标志
|
||||
syncController._lastPosition = null
|
||||
console.log('[useDualMapCompare] 智能同步已移除')
|
||||
|
||||
console.log('[useDualMapCompare] 智能同步已完全停止')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user