From 7b67d8e9b7cf7ea4c45254e590293d6f2f7534d0 Mon Sep 17 00:00:00 2001 From: Linghong Date: Fri, 7 Aug 2026 04:38:00 +0000 Subject: [PATCH] =?UTF-8?q?=E9=94=81=E5=AE=9A=E9=9F=B3=E9=A2=91=E9=A2=84?= =?UTF-8?q?=E8=AE=BE=E8=BD=A8=E9=81=93=E6=97=B6=E7=A6=81=E7=94=A8=E6=89=8B?= =?UTF-8?q?=E5=8A=A8=E6=A8=AA=E5=90=91=E6=BB=9A=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 锁定态给预设轨道加 --locked 修饰类,收紧为不可滚动容器并只放行纵向手势。 补齐 BGM 与 SFX 跑马灯锁定态的轨道滚动与相位保留断言。 --- .../ImageCanvasAudioPresetMarquee.tsx | 8 +++- ...anvasBackgroundMusicPresetMarquee.test.tsx | 47 +++++++++++++++++++ ...ageCanvasSoundEffectPresetMarquee.test.tsx | 8 +++- src/index.css | 7 +++ 4 files changed, 68 insertions(+), 2 deletions(-) diff --git a/src/components/image-editor/ImageCanvasAudioPresetMarquee.tsx b/src/components/image-editor/ImageCanvasAudioPresetMarquee.tsx index 35c8128ba..496c8bcfb 100644 --- a/src/components/image-editor/ImageCanvasAudioPresetMarquee.tsx +++ b/src/components/image-editor/ImageCanvasAudioPresetMarquee.tsx @@ -394,7 +394,13 @@ export function ImageCanvasAudioPresetMarquee<
{ ).toBe(true); }); + it('stops the track from being scrolled by hand while the panel is locked', () => { + const onSelectPreset = vi.fn(); + const { container, rerender } = renderMarquee({ onSelectPreset }); + expand(); + const viewport = getViewport(container); + + // 未锁定时轨道就是可滚动容器,交给原生横向滚动。 + expect( + viewport.classList.contains( + 'image-canvas-editor__background-music-presets-viewport--locked', + ), + ).toBe(false); + + rerender( + , + ); + + // 锁定时不只停自动循环,轨道本身也不再接受触摸 / 触控板的横向滚动。 + expect(frameCallbacks.size).toBe(0); + expect( + viewport.classList.contains( + 'image-canvas-editor__background-music-presets-viewport--locked', + ), + ).toBe(true); + // 相位保留:解锁后从原处继续,不跳回队列头。 + expect(viewport.scrollLeft).toBe(QUEUE_WIDTH); + + rerender( + , + ); + + expect( + viewport.classList.contains( + 'image-canvas-editor__background-music-presets-viewport--locked', + ), + ).toBe(false); + expect(viewport.scrollLeft).toBe(QUEUE_WIDTH); + }); + it('never starts the loop under reduced motion and reacts to runtime changes', () => { prefersReducedMotion = true; const { container } = renderMarquee(); diff --git a/src/components/image-editor/ImageCanvasSoundEffectPresetMarquee.test.tsx b/src/components/image-editor/ImageCanvasSoundEffectPresetMarquee.test.tsx index 772937ae8..699a8b6a2 100644 --- a/src/components/image-editor/ImageCanvasSoundEffectPresetMarquee.test.tsx +++ b/src/components/image-editor/ImageCanvasSoundEffectPresetMarquee.test.tsx @@ -44,7 +44,7 @@ describe('ImageCanvasSoundEffectPresetMarquee', () => { expect(onSelectPreset).toHaveBeenCalledWith(SOUND_EFFECT_PROMPT_PRESETS[0]); }); - it('keeps expansion and preset controls truly disabled while locked', () => { + it('keeps expansion, preset controls and the track scroll truly disabled while locked', () => { const view = render( { }) as HTMLButtonElement ).disabled, ).toBe(true); + // 「优化中锁定滚动」按轨道自身不可被手动横向滚动验收,不只是停掉自动循环。 + expect( + view.container.querySelector( + '.image-canvas-editor__background-music-presets-viewport--locked', + ), + ).toBeTruthy(); }); }); diff --git a/src/index.css b/src/index.css index 9a81e9423..ffdd1ce69 100644 --- a/src/index.css +++ b/src/index.css @@ -17105,6 +17105,13 @@ button { display: none; } +.image-canvas-editor__background-music-presets-viewport--locked { + /* 锁定期间轨道不再是用户可滚动容器,但保留 scrollLeft 相位,解锁后循环从原处继续。 */ + overflow-x: hidden; + /* 横向手势不再作用于轨道,纵向手势仍旧交给画布。 */ + touch-action: pan-y; +} + .image-canvas-editor__background-music-presets-queue { display: flex; flex: 0 0 auto;