From 93645a2640a64b8f2983b17cc016931e2b0fd3ac Mon Sep 17 00:00:00 2001 From: lyf <2514544224@qq.com> Date: Mon, 13 Jul 2026 22:18:18 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=A7=A6=E6=8E=A7=E7=BC=A9?= =?UTF-8?q?=E6=94=BE=E6=97=A0=E6=B3=95=E8=BF=94=E5=9B=9E=E5=BB=BA=E7=AD=91?= =?UTF-8?q?=E5=A4=96=E8=A7=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/map/ThreeMap.vue | 18 ++++++---- tests/e2e/three-map-camera-stability.spec.ts | 38 ++++++++++++++++++-- 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/src/components/map/ThreeMap.vue b/src/components/map/ThreeMap.vue index bcd1d38..0502f23 100644 --- a/src/components/map/ThreeMap.vue +++ b/src/components/map/ThreeMap.vue @@ -1638,18 +1638,22 @@ const easeInOutCubic = (t: number) => ( ) const cancelCameraTween = (options: { manual?: boolean } = {}) => { - if (cameraTween) { + const interruptedCameraTween = Boolean(cameraTween) + if (interruptedCameraTween) { cameraTween = null } if (options.manual) { - // 手动手势必须立即接管相机,避免已结束动画遗留的保护状态继续拦截自动切换。 + // 手动手势必须立即接管相机,避免相机动画的保护状态继续拦截自动切换。 isProgrammaticCameraChange = false clearProgrammaticCameraTimer() - const distance = controls?.getDistance() - if (typeof distance === 'number' && Number.isFinite(distance)) { - if (activeView.value === 'floor') { - // 用户中断楼层初始拟合时,使用中断后的稳定距离重新建立退出基准。 - autoSwitchStateMachine.setFloorInitialDistance(distance) + + if (interruptedCameraTween) { + const distance = controls?.getDistance() + if (typeof distance === 'number' && Number.isFinite(distance)) { + if (activeView.value === 'floor') { + // 用户中断楼层初始拟合时,使用中断后的稳定距离重新建立退出基准。 + autoSwitchStateMachine.setFloorInitialDistance(distance) + } } } } diff --git a/tests/e2e/three-map-camera-stability.spec.ts b/tests/e2e/three-map-camera-stability.spec.ts index 69f49eb..759b966 100644 --- a/tests/e2e/three-map-camera-stability.spec.ts +++ b/tests/e2e/three-map-camera-stability.spec.ts @@ -168,11 +168,35 @@ const showOverview = async (page: Page, testInfo: TestInfo, name: string) => { assertStableTransition(before, after) } -const exitOverviewWithZoomControl = async (page: Page, testInfo: TestInfo, name: string) => { +const exitOverviewWithZoomInput = async ( + page: Page, + testInfo: TestInfo, + name: string, + input: 'button' | 'wheel' | 'touch' +) => { const before = await getReport(page) await screenshot(page, testInfo, `${name}-before`) - await page.getByText('−', { exact: true }).click() + if (input === 'button') { + await page.getByText('−', { exact: true }).click() + } else if (input === 'wheel') { + await page.locator('canvas').hover() + await page.mouse.wheel(0, 3000) + } else { + const canvas = page.locator('canvas') + const box = await canvas.boundingBox() + expect(box, 'the touch zoom target must be visible').not.toBeNull() + + const session = await page.context().newCDPSession(page) + await session.send('Input.synthesizePinchGesture', { + x: Math.round(box!.x + box!.width / 2), + y: Math.round(box!.y + box!.height / 2), + scaleFactor: 0.5, + relativeSpeed: 800, + gestureSourceType: 'touch' + }) + } + await expect.poll(async () => (await getReport(page)).activeView, { timeout: 10_000 }).toBe('overview') const after = await getReport(page) @@ -231,5 +255,13 @@ test('ordinary exterior and floor switches preserve the GLB_METER camera project await switchFloor(page, testInfo, l1, 'exterior-l1-auto-exit') await switchFloor(page, testInfo, l2, 'l1-l2-auto-exit') - await exitOverviewWithZoomControl(page, testInfo, 'l2-exterior-auto-exit') + await exitOverviewWithZoomInput(page, testInfo, 'l2-exterior-button-exit', 'button') + + await switchFloor(page, testInfo, l1, 'exterior-l1-wheel-exit') + await switchFloor(page, testInfo, l2, 'l1-l2-wheel-exit') + await exitOverviewWithZoomInput(page, testInfo, 'l2-exterior-wheel-exit', 'wheel') + + await switchFloor(page, testInfo, l1, 'exterior-l1-touch-exit') + await switchFloor(page, testInfo, l2, 'l1-l2-touch-exit') + await exitOverviewWithZoomInput(page, testInfo, 'l2-exterior-touch-exit', 'touch') })