Merge branch 'dev' of http://222.212.85.86:8222/bdzl2/bxztApp into dev
This commit is contained in:
commit
0dca401b1c
@ -87,46 +87,66 @@ export function use3DTiles() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let timeoutId = null
|
||||||
|
let eventHandler = null
|
||||||
|
|
||||||
|
// 统一清理函数
|
||||||
|
const cleanup = () => {
|
||||||
|
if (timeoutId) {
|
||||||
|
clearTimeout(timeoutId)
|
||||||
|
timeoutId = null
|
||||||
|
}
|
||||||
|
if (eventHandler) {
|
||||||
|
tileset.initialTilesLoaded.removeEventListener(eventHandler)
|
||||||
|
eventHandler = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 步骤1:等待 Tileset 基础就绪
|
// 步骤1:等待 Tileset 基础就绪
|
||||||
await tileset.readyPromise
|
await tileset.readyPromise
|
||||||
console.log('[use3DTiles] Tileset readyPromise 已完成')
|
console.log('[use3DTiles] Tileset readyPromise 已完成')
|
||||||
|
|
||||||
// 步骤2:等待初始瓦片加载完成(带超时)
|
// 步骤2:早期出口 - 快速检查
|
||||||
|
if (tileset.tilesLoaded) {
|
||||||
|
console.log('[use3DTiles] 瓦片已加载,直接继续')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 步骤3:等待初始瓦片加载完成(带超时)
|
||||||
console.log('[use3DTiles] 等待初始瓦片加载...')
|
console.log('[use3DTiles] 等待初始瓦片加载...')
|
||||||
|
|
||||||
await Promise.race([
|
await Promise.race([
|
||||||
// 等待initialTilesLoaded事件
|
// 等待 initialTilesLoaded 事件
|
||||||
new Promise((resolve) => {
|
new Promise((resolve) => {
|
||||||
const handleInitialTilesLoaded = () => {
|
eventHandler = () => {
|
||||||
console.log('[use3DTiles] 初始瓦片加载完成(事件触发)')
|
console.log('[use3DTiles] 初始瓦片加载完成(事件触发)')
|
||||||
tileset.initialTilesLoaded.removeEventListener(handleInitialTilesLoaded)
|
cleanup()
|
||||||
resolve()
|
|
||||||
}
|
|
||||||
|
|
||||||
tileset.initialTilesLoaded.addEventListener(handleInitialTilesLoaded)
|
|
||||||
|
|
||||||
// 如果已经加载完成,可能事件已经触发过了,直接resolve
|
|
||||||
// 通过检查tileset.tilesLoaded来判断
|
|
||||||
if (tileset.tilesLoaded) {
|
|
||||||
console.log('[use3DTiles] 瓦片已加载,直接继续')
|
|
||||||
tileset.initialTilesLoaded.removeEventListener(handleInitialTilesLoaded)
|
|
||||||
resolve()
|
resolve()
|
||||||
}
|
}
|
||||||
|
tileset.initialTilesLoaded.addEventListener(eventHandler)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// 超时机制
|
// 超时机制
|
||||||
new Promise((resolve) => {
|
new Promise((_, reject) => {
|
||||||
setTimeout(() => {
|
timeoutId = setTimeout(() => {
|
||||||
console.warn(`[use3DTiles] 等待瓦片加载超时(${timeout}ms),继续执行`)
|
cleanup()
|
||||||
resolve()
|
reject(new Error(`等待瓦片加载超时(${timeout}ms)`))
|
||||||
}, timeout)
|
}, timeout)
|
||||||
})
|
})
|
||||||
])
|
])
|
||||||
|
|
||||||
console.log('[use3DTiles] Tileset 已完全就绪')
|
console.log('[use3DTiles] Tileset 已完全就绪')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[use3DTiles] 等待 Tileset 就绪失败:', error)
|
if (error.message && error.message.includes('超时')) {
|
||||||
|
// 超时但继续执行(保持原有行为)
|
||||||
|
console.warn(`[use3DTiles] ${error.message},继续执行`)
|
||||||
|
} else {
|
||||||
|
console.error('[use3DTiles] 等待 Tileset 就绪失败:', error)
|
||||||
|
}
|
||||||
// 即使失败也不抛出异常,允许程序继续执行
|
// 即使失败也不抛出异常,允许程序继续执行
|
||||||
|
} finally {
|
||||||
|
cleanup() // 保险清理
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -105,10 +105,32 @@ export function useDualMapCompare() {
|
|||||||
let isSyncing = false
|
let isSyncing = false
|
||||||
const handleCameraSync = () => {
|
const handleCameraSync = () => {
|
||||||
if (isSyncing) return
|
if (isSyncing) return
|
||||||
|
|
||||||
|
// 防御检查1:viewer 存在性检查
|
||||||
|
if (!rightViewerInstance || !leftViewerInstance) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 防御检查2:viewer destroyed 状态检查
|
||||||
|
if (rightViewerInstance.isDestroyed?.() || leftViewerInstance.isDestroyed?.()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
isSyncing = true
|
isSyncing = true
|
||||||
|
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
try {
|
try {
|
||||||
|
// 再次检查(requestAnimationFrame 可能延迟执行)
|
||||||
|
if (!rightViewerInstance || !leftViewerInstance) {
|
||||||
|
isSyncing = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rightViewerInstance.isDestroyed?.() || leftViewerInstance.isDestroyed?.()) {
|
||||||
|
isSyncing = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const rightCamera = rightViewerInstance.camera
|
const rightCamera = rightViewerInstance.camera
|
||||||
leftViewerInstance.camera.setView({
|
leftViewerInstance.camera.setView({
|
||||||
destination: rightCamera.position.clone(),
|
destination: rightCamera.position.clone(),
|
||||||
@ -132,8 +154,13 @@ export function useDualMapCompare() {
|
|||||||
_moveEndHandler: null,
|
_moveEndHandler: null,
|
||||||
_lastPosition: null,
|
_lastPosition: null,
|
||||||
_interval: null,
|
_interval: null,
|
||||||
|
_stopped: false, // 新增:原子性停止标志
|
||||||
|
_moveEndReceived: false, // 新增:标记 moveEnd 是否已触发
|
||||||
|
|
||||||
start: () => {
|
start: () => {
|
||||||
|
// 重置停止标志
|
||||||
|
syncController._stopped = false
|
||||||
|
|
||||||
const controller = rightViewerInstance.scene.screenSpaceCameraController
|
const controller = rightViewerInstance.scene.screenSpaceCameraController
|
||||||
|
|
||||||
if (!controller) {
|
if (!controller) {
|
||||||
@ -145,13 +172,27 @@ export function useDualMapCompare() {
|
|||||||
if (typeof rightViewerInstance.camera.moveStart?.addEventListener === 'function' &&
|
if (typeof rightViewerInstance.camera.moveStart?.addEventListener === 'function' &&
|
||||||
typeof rightViewerInstance.camera.moveEnd?.addEventListener === 'function') {
|
typeof rightViewerInstance.camera.moveEnd?.addEventListener === 'function') {
|
||||||
|
|
||||||
// 监听相机移动开始(替代所有操作类型监听)
|
// 监听相机移动开始
|
||||||
const moveStartHandler = rightViewerInstance.camera.moveStart.addEventListener(() => {
|
const moveStartHandler = rightViewerInstance.camera.moveStart.addEventListener(() => {
|
||||||
|
if (syncController._stopped) return // 检查停止标志
|
||||||
|
|
||||||
syncController._isUserInteracting = true
|
syncController._isUserInteracting = true
|
||||||
console.log('[useDualMapCompare] 捕获相机操作开始')
|
console.log('[useDualMapCompare] 捕获相机操作开始')
|
||||||
|
|
||||||
// 新增拖动持续监听
|
// 改进:只在首次触发时启动递归
|
||||||
const onDragFrame = () => {
|
const onDragFrame = () => {
|
||||||
|
// 停止检查
|
||||||
|
if (syncController._stopped) {
|
||||||
|
console.log('[useDualMapCompare] 停止标志已设置,退出递归')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// viewer 有效性检查
|
||||||
|
if (!rightViewerInstance || rightViewerInstance.isDestroyed?.()) {
|
||||||
|
console.log('[useDualMapCompare] Viewer已销毁,退出递归')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (syncController._isUserInteracting) {
|
if (syncController._isUserInteracting) {
|
||||||
console.log('[useDualMapCompare] 主同步触发')
|
console.log('[useDualMapCompare] 主同步触发')
|
||||||
handleCameraSync()
|
handleCameraSync()
|
||||||
@ -161,12 +202,17 @@ export function useDualMapCompare() {
|
|||||||
requestAnimationFrame(onDragFrame)
|
requestAnimationFrame(onDragFrame)
|
||||||
})
|
})
|
||||||
|
|
||||||
// 2. 同步逻辑
|
syncController._interactionHandlers.push(moveStartHandler)
|
||||||
|
|
||||||
|
// 2. 监听相机移动结束
|
||||||
syncController._moveEndHandler = rightViewerInstance.camera.moveEnd.addEventListener(() => {
|
syncController._moveEndHandler = rightViewerInstance.camera.moveEnd.addEventListener(() => {
|
||||||
|
if (syncController._stopped) return // 检查停止标志
|
||||||
|
|
||||||
if (syncController._isUserInteracting) {
|
if (syncController._isUserInteracting) {
|
||||||
console.log('[useDualMapCompare] 主同步触发')
|
console.log('[useDualMapCompare] moveEnd 事件触发,等待相机完全停止...')
|
||||||
handleCameraSync()
|
// 不要立即重置 _isUserInteracting,让 setInterval 继续检测
|
||||||
syncController._isUserInteracting = false
|
// 标记为"移动已结束但可能还在惯性滑动"
|
||||||
|
syncController._moveEndReceived = true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -175,62 +221,113 @@ export function useDualMapCompare() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 保险同步逻辑
|
// 3. 保险同步逻辑(setInterval)
|
||||||
syncController._lastPosition = new Cesium.Cartesian3()
|
syncController._lastPosition = new Cesium.Cartesian3()
|
||||||
|
syncController._moveEndReceived = false // 重置标志
|
||||||
syncController._interval = setInterval(() => {
|
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 isMoving = controller.isMoving
|
||||||
const currentPosition = rightViewerInstance.camera.position
|
const currentPosition = rightViewerInstance.camera.position
|
||||||
|
|
||||||
if (syncController._isUserInteracting) {
|
if (syncController._isUserInteracting) {
|
||||||
if (isMoving) {
|
if (isMoving) {
|
||||||
|
// 相机正在移动,持续更新位置
|
||||||
Cesium.Cartesian3.clone(currentPosition, syncController._lastPosition)
|
Cesium.Cartesian3.clone(currentPosition, syncController._lastPosition)
|
||||||
|
syncController._moveEndReceived = false // 重置标志
|
||||||
} else {
|
} else {
|
||||||
const positionChanged = !Cesium.Cartesian3.equalsEpsilon(
|
// 相机已停止移动
|
||||||
currentPosition,
|
if (syncController._moveEndReceived) {
|
||||||
syncController._lastPosition,
|
// moveEnd 已触发且相机已停止,执行最终同步
|
||||||
0.1
|
const positionChanged = !Cesium.Cartesian3.equalsEpsilon(
|
||||||
)
|
currentPosition,
|
||||||
if (positionChanged) {
|
syncController._lastPosition,
|
||||||
console.log('[useDualMapCompare] 保险同步触发')
|
0.001 // 更高精度
|
||||||
handleCameraSync()
|
)
|
||||||
}
|
|
||||||
if (!controller.isMoving) {
|
if (positionChanged) {
|
||||||
|
console.log('[useDualMapCompare] 相机完全停止,执行最终同步')
|
||||||
|
handleCameraSync()
|
||||||
|
Cesium.Cartesian3.clone(currentPosition, syncController._lastPosition)
|
||||||
|
} else {
|
||||||
|
console.log('[useDualMapCompare] 相机完全停止,位置无变化')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置状态
|
||||||
syncController._isUserInteracting = false
|
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)
|
}, 300)
|
||||||
|
|
||||||
console.log('[useDualMapCompare] 智能同步设置完成')
|
console.log('[useDualMapCompare] 智能同步已启动')
|
||||||
},
|
},
|
||||||
|
|
||||||
stop: () => {
|
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) {
|
if (syncController._interval) {
|
||||||
clearInterval(syncController._interval)
|
clearInterval(syncController._interval)
|
||||||
syncController._interval = null
|
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._isUserInteracting = false
|
||||||
|
syncController._moveEndReceived = false // 重置标志
|
||||||
syncController._lastPosition = null
|
syncController._lastPosition = null
|
||||||
console.log('[useDualMapCompare] 智能同步已移除')
|
|
||||||
|
console.log('[useDualMapCompare] 智能同步已完全停止')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -120,7 +120,7 @@ export function useEntityAnimation() {
|
|||||||
viewer.clock.startTime = startTime.clone()
|
viewer.clock.startTime = startTime.clone()
|
||||||
viewer.clock.stopTime = stopTime.clone()
|
viewer.clock.stopTime = stopTime.clone()
|
||||||
viewer.clock.currentTime = startTime.clone()
|
viewer.clock.currentTime = startTime.clone()
|
||||||
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP // 动画结束后停止
|
viewer.clock.clockRange = Cesium.ClockRange.CLAMPED // 动画到达终点后停止,不循环
|
||||||
viewer.clock.multiplier = 1 // 实时速度
|
viewer.clock.multiplier = 1 // 实时速度
|
||||||
viewer.clock.shouldAnimate = true
|
viewer.clock.shouldAnimate = true
|
||||||
|
|
||||||
@ -385,7 +385,7 @@ export function useEntityAnimation() {
|
|||||||
viewer.clock.startTime = startTime.clone()
|
viewer.clock.startTime = startTime.clone()
|
||||||
viewer.clock.stopTime = stopTime.clone()
|
viewer.clock.stopTime = stopTime.clone()
|
||||||
viewer.clock.currentTime = startTime.clone()
|
viewer.clock.currentTime = startTime.clone()
|
||||||
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP
|
viewer.clock.clockRange = Cesium.ClockRange.CLAMPED // 动画到达终点后停止,不循环
|
||||||
viewer.clock.multiplier = 1
|
viewer.clock.multiplier = 1
|
||||||
viewer.clock.shouldAnimate = true
|
viewer.clock.shouldAnimate = true
|
||||||
|
|
||||||
@ -470,7 +470,12 @@ export function useEntityAnimation() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 计算动画时长(使用速度倍数)
|
// 计算动画时长(使用速度倍数)
|
||||||
const speedMultiplier = options.speedMultiplier || 10
|
// 装备移动速度更快(speedMultiplier 更大 = 动画时间更短 = 移动更快)
|
||||||
|
const baseSpeedMultiplier = options.speedMultiplier || 10
|
||||||
|
const speedMultiplier = route.type === 'equipment'
|
||||||
|
? baseSpeedMultiplier * 1.5 // 装备速度是人员的1.5倍
|
||||||
|
: baseSpeedMultiplier // 人员保持原速
|
||||||
|
|
||||||
const animationDuration = Math.min(
|
const animationDuration = Math.min(
|
||||||
Math.max(route.duration / speedMultiplier, 30), // 最小30秒
|
Math.max(route.duration / speedMultiplier, 30), // 最小30秒
|
||||||
120 // 最大120秒
|
120 // 最大120秒
|
||||||
@ -510,6 +515,14 @@ export function useEntityAnimation() {
|
|||||||
const icon = route.type === 'equipment' ? deviceIcon : soldierIcon
|
const icon = route.type === 'equipment' ? deviceIcon : soldierIcon
|
||||||
const trailColor = route.type === 'equipment' ? Cesium.Color.ORANGE : Cesium.Color.CYAN
|
const trailColor = route.type === 'equipment' ? Cesium.Color.ORANGE : Cesium.Color.CYAN
|
||||||
|
|
||||||
|
// 日志输出:显示每个实体的动画时长
|
||||||
|
console.log(
|
||||||
|
`[useEntityAnimation] ${route.name} (${route.type}): ` +
|
||||||
|
`原始时长=${Math.round(route.duration)}秒, ` +
|
||||||
|
`速度倍数=${speedMultiplier.toFixed(1)}, ` +
|
||||||
|
`动画时长=${Math.round(animationDuration)}秒`
|
||||||
|
)
|
||||||
|
|
||||||
// 创建动画实体
|
// 创建动画实体
|
||||||
return viewer.entities.add({
|
return viewer.entities.add({
|
||||||
availability: new Cesium.TimeIntervalCollection([
|
availability: new Cesium.TimeIntervalCollection([
|
||||||
@ -584,7 +597,7 @@ export function useEntityAnimation() {
|
|||||||
viewer.clock.startTime = startTime.clone()
|
viewer.clock.startTime = startTime.clone()
|
||||||
viewer.clock.stopTime = stopTime.clone()
|
viewer.clock.stopTime = stopTime.clone()
|
||||||
viewer.clock.currentTime = startTime.clone()
|
viewer.clock.currentTime = startTime.clone()
|
||||||
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP
|
viewer.clock.clockRange = Cesium.ClockRange.CLAMPED // 动画到达终点后停止,不循环
|
||||||
viewer.clock.multiplier = 1
|
viewer.clock.multiplier = 1
|
||||||
viewer.clock.shouldAnimate = true
|
viewer.clock.shouldAnimate = true
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user