From 20bf2bd5d8005eac7d9082bc96758969281a5968 Mon Sep 17 00:00:00 2001 From: 3dtours Date: Tue, 21 Jul 2026 11:42:03 +0700 Subject: [PATCH] fix: zoom in with playhead on center screen --- app/static/js/app.jsx | 14 +++++++------- app/static/js/app.precompiled.js | 14 +++++++------- app/storage/sonicforge.db | Bin 45056 -> 45056 bytes 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/app/static/js/app.jsx b/app/static/js/app.jsx index 23a9ad0..12b71ff 100644 --- a/app/static/js/app.jsx +++ b/app/static/js/app.jsx @@ -3318,6 +3318,8 @@ const App = () => { const rulerAnchorRef = useRef(null); const isDraggingRulerRef = useRef(false); const handlePlayPauseRef = useRef(null); + const currentTimeRef = useRef(currentTime); + currentTimeRef.current = currentTime; // ── Keyboard Shortcuts ── const handleUndoRef = useRef(handleUndo); @@ -4881,18 +4883,16 @@ const App = () => { const handleWheel = e => { if (e.ctrlKey || e.metaKey) { e.preventDefault(); - const rect = timeline.getBoundingClientRect(); - const mouseXInViewport = e.clientX - rect.left; - const mouseXInCanvas = mouseXInViewport + timeline.scrollLeft; - const anchorTime = mouseXInCanvas / zoom; const zoomFactor = e.deltaY > 0 ? 0.9 : 1.1; setZoom(prevZoom => { let newZoom = prevZoom * zoomFactor; if (newZoom < minZoom) newZoom = minZoom; if (newZoom > 50000) newZoom = 50000; - const newMouseXInCanvas = anchorTime * newZoom; requestAnimationFrame(() => { - timeline.scrollLeft = newMouseXInCanvas - mouseXInViewport; + const centerTime = currentTimeRef.current; + const newCenterX = centerTime * newZoom; + const viewportWidth = timeline.clientWidth; + timeline.scrollLeft = newCenterX - viewportWidth / 2; }); return newZoom; }); @@ -4905,7 +4905,7 @@ const App = () => { passive: false }); return () => timeline.removeEventListener('wheel', handleWheel); - }, [zoom, minZoom, maxDuration, activeTab]); + }, [minZoom]); // ── Update Playhead ── const startSubTabPlayback = (st, offsetWallTime) => { diff --git a/app/static/js/app.precompiled.js b/app/static/js/app.precompiled.js index 23a9ad0..12b71ff 100644 --- a/app/static/js/app.precompiled.js +++ b/app/static/js/app.precompiled.js @@ -3318,6 +3318,8 @@ const App = () => { const rulerAnchorRef = useRef(null); const isDraggingRulerRef = useRef(false); const handlePlayPauseRef = useRef(null); + const currentTimeRef = useRef(currentTime); + currentTimeRef.current = currentTime; // ── Keyboard Shortcuts ── const handleUndoRef = useRef(handleUndo); @@ -4881,18 +4883,16 @@ const App = () => { const handleWheel = e => { if (e.ctrlKey || e.metaKey) { e.preventDefault(); - const rect = timeline.getBoundingClientRect(); - const mouseXInViewport = e.clientX - rect.left; - const mouseXInCanvas = mouseXInViewport + timeline.scrollLeft; - const anchorTime = mouseXInCanvas / zoom; const zoomFactor = e.deltaY > 0 ? 0.9 : 1.1; setZoom(prevZoom => { let newZoom = prevZoom * zoomFactor; if (newZoom < minZoom) newZoom = minZoom; if (newZoom > 50000) newZoom = 50000; - const newMouseXInCanvas = anchorTime * newZoom; requestAnimationFrame(() => { - timeline.scrollLeft = newMouseXInCanvas - mouseXInViewport; + const centerTime = currentTimeRef.current; + const newCenterX = centerTime * newZoom; + const viewportWidth = timeline.clientWidth; + timeline.scrollLeft = newCenterX - viewportWidth / 2; }); return newZoom; }); @@ -4905,7 +4905,7 @@ const App = () => { passive: false }); return () => timeline.removeEventListener('wheel', handleWheel); - }, [zoom, minZoom, maxDuration, activeTab]); + }, [minZoom]); // ── Update Playhead ── const startSubTabPlayback = (st, offsetWallTime) => { diff --git a/app/storage/sonicforge.db b/app/storage/sonicforge.db index 42eb543661183597fed4bb674d5fe12eb128b75f..dcb73abad909e469f9d692e3652b70fff857f7f9 100644 GIT binary patch delta 43 zcmZp8z|`=7X@WGP#6%fqMv09Hk87EY4GbpB*IRFHtkYy<-6tQixnT49`alB!O~wzL delta 39 vcmZp8z|`=7X@WGP$V3@uMv;vPk83B()Z1-ttkYy<-Fs}4!IRDF>jMn{E7K42