左右对比部分 调整同步方式 左侧可以任意拖动 只有右侧拖动时才会触发同步
This commit is contained in:
parent
8d9a0112ce
commit
47074b6d56
@ -69,14 +69,14 @@ export function useDualMapCompare() {
|
|||||||
viewer.cesiumWidget.creditContainer.style.display = 'none'
|
viewer.cesiumWidget.creditContainer.style.display = 'none'
|
||||||
|
|
||||||
// 完全禁用左侧Viewer的所有交互(只作为对比显示)
|
// 完全禁用左侧Viewer的所有交互(只作为对比显示)
|
||||||
viewer.scene.screenSpaceCameraController.enableRotate = false
|
// viewer.scene.screenSpaceCameraController.enableRotate = false
|
||||||
viewer.scene.screenSpaceCameraController.enableTranslate = false
|
// viewer.scene.screenSpaceCameraController.enableTranslate = false
|
||||||
viewer.scene.screenSpaceCameraController.enableZoom = false
|
// viewer.scene.screenSpaceCameraController.enableZoom = false
|
||||||
viewer.scene.screenSpaceCameraController.enableTilt = false
|
// viewer.scene.screenSpaceCameraController.enableTilt = false
|
||||||
viewer.scene.screenSpaceCameraController.enableLook = false
|
// viewer.scene.screenSpaceCameraController.enableLook = false
|
||||||
|
|
||||||
leftViewer.value = viewer
|
leftViewer.value = viewer
|
||||||
console.log('[useDualMapCompare] 左侧Viewer初始化成功(交互已禁用)')
|
console.log('[useDualMapCompare] 左侧Viewer初始化成功(交互已启用)') // 关键修改
|
||||||
|
|
||||||
return viewer
|
return viewer
|
||||||
}
|
}
|
||||||
@ -84,7 +84,6 @@ export function useDualMapCompare() {
|
|||||||
/**
|
/**
|
||||||
* 设置单向相机同步(右→左)
|
* 设置单向相机同步(右→左)
|
||||||
* 右侧主地图驱动,左侧对比地图跟随
|
* 右侧主地图驱动,左侧对比地图跟随
|
||||||
* 使用 postRender 实现逐帧同步,直接传递 position 引用以获得最佳性能
|
|
||||||
* @param {Cesium.Viewer} rightViewerInstance - 右侧Viewer(主地图,驱动者)
|
* @param {Cesium.Viewer} rightViewerInstance - 右侧Viewer(主地图,驱动者)
|
||||||
* @param {Cesium.Viewer} leftViewerInstance - 左侧Viewer(对比地图,跟随者)
|
* @param {Cesium.Viewer} leftViewerInstance - 左侧Viewer(对比地图,跟随者)
|
||||||
*/
|
*/
|
||||||
@ -94,42 +93,152 @@ export function useDualMapCompare() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('[useDualMapCompare] 设置单向相机同步(右→左)...')
|
console.log('[useDualMapCompare] 设置智能相机同步(右→左)...')
|
||||||
|
|
||||||
/**
|
/** 同步相机状态(带防抖) */
|
||||||
* 相机同步处理函数
|
let isSyncing = false
|
||||||
* 在右侧 Viewer 的 postRender 中调用,将右侧相机状态同步到左侧
|
|
||||||
*/
|
|
||||||
const handleCameraSync = () => {
|
const handleCameraSync = () => {
|
||||||
// 检查 Viewer 是否有效
|
if (isSyncing) return
|
||||||
if (!leftViewerInstance || leftViewerInstance.isDestroyed()) return
|
isSyncing = true
|
||||||
if (!rightViewerInstance || rightViewerInstance.isDestroyed()) return
|
|
||||||
|
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
try {
|
||||||
const rightCamera = rightViewerInstance.camera
|
const rightCamera = rightViewerInstance.camera
|
||||||
|
|
||||||
// 直接传递 position 引用(不 clone),获得最佳性能
|
|
||||||
// Cesium 内部会处理拷贝,且在单向同步场景下安全
|
|
||||||
leftViewerInstance.camera.setView({
|
leftViewerInstance.camera.setView({
|
||||||
destination: rightCamera.position,
|
destination: rightCamera.position.clone(),
|
||||||
orientation: {
|
orientation: {
|
||||||
heading: rightCamera.heading,
|
heading: rightCamera.heading,
|
||||||
pitch: rightCamera.pitch,
|
pitch: rightCamera.pitch,
|
||||||
roll: rightCamera.roll
|
roll: rightCamera.roll
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('[useDualMapCompare] 同步异常:', e)
|
||||||
|
} finally {
|
||||||
|
isSyncing = false
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 只在右侧 Viewer 的 postRender 中注册同步函数
|
const syncController = {
|
||||||
// 确保右侧相机更新完成后再同步到左侧
|
_isUserInteracting: false,
|
||||||
rightViewerInstance.scene.postRender.addEventListener(handleCameraSync)
|
_interactionHandlers: [], // 存储 moveStart 监听器
|
||||||
|
_moveEndHandler: null,
|
||||||
|
_lastPosition: null,
|
||||||
|
_interval: null,
|
||||||
|
|
||||||
|
start: () => {
|
||||||
|
const controller = rightViewerInstance.scene.screenSpaceCameraController
|
||||||
|
|
||||||
|
if (!controller) {
|
||||||
|
console.error('[useDualMapCompare] screenSpaceCameraController未初始化')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 事件监听逻辑
|
||||||
|
if (typeof rightViewerInstance.camera.moveStart?.addEventListener === 'function' &&
|
||||||
|
typeof rightViewerInstance.camera.moveEnd?.addEventListener === 'function') {
|
||||||
|
|
||||||
|
// 监听相机移动开始(替代所有操作类型监听)
|
||||||
|
const moveStartHandler = rightViewerInstance.camera.moveStart.addEventListener(() => {
|
||||||
|
syncController._isUserInteracting = true
|
||||||
|
console.log('[useDualMapCompare] 捕获相机操作开始')
|
||||||
|
|
||||||
|
// 新增拖动持续监听
|
||||||
|
const onDragFrame = () => {
|
||||||
|
if (syncController._isUserInteracting) {
|
||||||
|
console.log('[useDualMapCompare] 主同步触发')
|
||||||
|
handleCameraSync()
|
||||||
|
requestAnimationFrame(onDragFrame)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
requestAnimationFrame(onDragFrame)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 2. 同步逻辑
|
||||||
|
syncController._moveEndHandler = rightViewerInstance.camera.moveEnd.addEventListener(() => {
|
||||||
|
if (syncController._isUserInteracting) {
|
||||||
|
console.log('[useDualMapCompare] 主同步触发')
|
||||||
|
handleCameraSync()
|
||||||
|
syncController._isUserInteracting = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
} else {
|
||||||
|
console.warn(`[useDualMapCompare] 相机事件不可用,当前Cesium版本: ${Cesium.VERSION}`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 保险同步逻辑
|
||||||
|
syncController._lastPosition = new Cesium.Cartesian3()
|
||||||
|
syncController._interval = setInterval(() => {
|
||||||
|
const isMoving = controller.isMoving
|
||||||
|
const currentPosition = rightViewerInstance.camera.position
|
||||||
|
|
||||||
|
if (syncController._isUserInteracting) {
|
||||||
|
if (isMoving) {
|
||||||
|
Cesium.Cartesian3.clone(currentPosition, syncController._lastPosition)
|
||||||
|
} else {
|
||||||
|
const positionChanged = !Cesium.Cartesian3.equalsEpsilon(
|
||||||
|
currentPosition,
|
||||||
|
syncController._lastPosition,
|
||||||
|
0.1
|
||||||
|
)
|
||||||
|
if (positionChanged) {
|
||||||
|
console.log('[useDualMapCompare] 保险同步触发')
|
||||||
|
handleCameraSync()
|
||||||
|
}
|
||||||
|
if (!controller.isMoving) {
|
||||||
|
syncController._isUserInteracting = false
|
||||||
|
}
|
||||||
|
Cesium.Cartesian3.clone(currentPosition, syncController._lastPosition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 300)
|
||||||
|
|
||||||
|
console.log('[useDualMapCompare] 智能同步设置完成')
|
||||||
|
},
|
||||||
|
|
||||||
|
stop: () => {
|
||||||
|
const controller = rightViewerInstance.scene.screenSpaceCameraController
|
||||||
|
|
||||||
|
// 移除 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
|
||||||
|
}
|
||||||
|
|
||||||
|
syncController._isUserInteracting = false
|
||||||
|
syncController._lastPosition = null
|
||||||
|
console.log('[useDualMapCompare] 智能同步已移除')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 启动监听
|
||||||
|
syncController.start()
|
||||||
|
|
||||||
// 保存移除函数
|
// 保存移除函数
|
||||||
cameraSyncRemover = () => {
|
cameraSyncRemover = () => {
|
||||||
rightViewerInstance.scene.postRender.removeEventListener(handleCameraSync)
|
syncController.stop()
|
||||||
console.log('[useDualMapCompare] 相机同步已移除')
|
console.log('[useDualMapCompare] 智能同步已移除')
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('[useDualMapCompare] 单向相机同步设置完成')
|
console.log('[useDualMapCompare] 智能同步设置完成')
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -179,8 +288,29 @@ export function useDualMapCompare() {
|
|||||||
// 先设置状态,触发CSS动画
|
// 先设置状态,触发CSS动画
|
||||||
isCompareMode.value = true
|
isCompareMode.value = true
|
||||||
|
|
||||||
// 等待CSS过渡完成(300ms + 50ms buffer)
|
// 增强型布局等待策略
|
||||||
await new Promise(resolve => setTimeout(resolve, 350))
|
await new Promise(resolve => {
|
||||||
|
// 1. 基础等待 → 2. 强制重绘 → 3. 循环检查
|
||||||
|
setTimeout(() => {
|
||||||
|
// 强制触发浏览器重绘
|
||||||
|
void leftContainer.offsetWidth
|
||||||
|
|
||||||
|
// 3. 循环验证容器尺寸
|
||||||
|
const startTime = Date.now()
|
||||||
|
const checkLayout = () => {
|
||||||
|
if (leftContainer.clientWidth > 0 && leftContainer.clientHeight > 0) {
|
||||||
|
resolve()
|
||||||
|
} else if (Date.now() - startTime < 2000) { // 总等待不超过2秒
|
||||||
|
setTimeout(checkLayout, 50)
|
||||||
|
} else {
|
||||||
|
console.error('左侧容器最终尺寸:',
|
||||||
|
`width: ${leftContainer.clientWidth}px, height: ${leftContainer.clientHeight}px`)
|
||||||
|
throw new Error('左侧容器布局超时')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkLayout()
|
||||||
|
}, 350) // 原等待时间保持
|
||||||
|
})
|
||||||
|
|
||||||
// 初始化左侧Viewer
|
// 初始化左侧Viewer
|
||||||
const leftViewerInstance = initLeftViewer(leftContainer)
|
const leftViewerInstance = initLeftViewer(leftContainer)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user