feat: enhance scroll position management during page transitions

This commit is contained in:
LTbinglingfeng
2026-01-31 00:36:13 +08:00
parent 3d83d0bfe2
commit 3cdcb7a2a3

View File

@@ -43,6 +43,8 @@ export function PageTransition({
const transitionDirectionRef = useRef<TransitionDirection>('forward'); const transitionDirectionRef = useRef<TransitionDirection>('forward');
const transitionVariantRef = useRef<TransitionVariant>('vertical'); const transitionVariantRef = useRef<TransitionVariant>('vertical');
const exitScrollOffsetRef = useRef(0); const exitScrollOffsetRef = useRef(0);
const enterScrollOffsetRef = useRef(0);
const scrollPositionsRef = useRef(new Map<string, number>());
const nextLayersRef = useRef<Layer[] | null>(null); const nextLayersRef = useRef<Layer[] | null>(null);
const [isAnimating, setIsAnimating] = useState(false); const [isAnimating, setIsAnimating] = useState(false);
@@ -69,7 +71,11 @@ export function PageTransition({
if (location.key === currentLayerKey) return; if (location.key === currentLayerKey) return;
if (currentLayerPathname === location.pathname) return; if (currentLayerPathname === location.pathname) return;
const scrollContainer = resolveScrollContainer(); const scrollContainer = resolveScrollContainer();
exitScrollOffsetRef.current = scrollContainer?.scrollTop ?? 0; const exitScrollOffset = scrollContainer?.scrollTop ?? 0;
exitScrollOffsetRef.current = exitScrollOffset;
scrollPositionsRef.current.set(currentLayerKey, exitScrollOffset);
enterScrollOffsetRef.current = scrollPositionsRef.current.get(location.key) ?? 0;
const resolveOrderIndex = (pathname?: string) => { const resolveOrderIndex = (pathname?: string) => {
if (!getRouteOrder || !pathname) return null; if (!getRouteOrder || !pathname) return null;
const index = getRouteOrder(pathname); const index = getRouteOrder(pathname);
@@ -162,17 +168,23 @@ export function PageTransition({
const exitingLayerEl = exitingLayerRef.current; const exitingLayerEl = exitingLayerRef.current;
const transitionVariant = transitionVariantRef.current; const transitionVariant = transitionVariantRef.current;
gsap.set(currentLayerEl, { clearProps: 'transform,opacity,boxShadow' });
if (exitingLayerEl) {
gsap.set(exitingLayerEl, { clearProps: 'transform,opacity,boxShadow' });
}
const scrollContainer = resolveScrollContainer(); const scrollContainer = resolveScrollContainer();
const scrollOffset = exitScrollOffsetRef.current; const exitScrollOffset = exitScrollOffsetRef.current;
if (scrollContainer && scrollOffset > 0) { const enterScrollOffset = enterScrollOffsetRef.current;
scrollContainer.scrollTo({ top: 0, left: 0, behavior: 'auto' }); if (scrollContainer && exitScrollOffset !== enterScrollOffset) {
scrollContainer.scrollTo({ top: enterScrollOffset, left: 0, behavior: 'auto' });
} }
const transitionDirection = transitionDirectionRef.current; const transitionDirection = transitionDirectionRef.current;
const isForward = transitionDirection === 'forward'; const isForward = transitionDirection === 'forward';
const enterFromY = isForward ? VERTICAL_TRAVEL_DISTANCE : -VERTICAL_TRAVEL_DISTANCE; const enterFromY = isForward ? VERTICAL_TRAVEL_DISTANCE : -VERTICAL_TRAVEL_DISTANCE;
const exitToY = isForward ? -VERTICAL_TRAVEL_DISTANCE : VERTICAL_TRAVEL_DISTANCE; const exitToY = isForward ? -VERTICAL_TRAVEL_DISTANCE : VERTICAL_TRAVEL_DISTANCE;
const exitBaseY = scrollOffset ? -scrollOffset : 0; const exitBaseY = enterScrollOffset - exitScrollOffset;
const tl = gsap.timeline({ const tl = gsap.timeline({
onComplete: () => { onComplete: () => {
@@ -184,6 +196,9 @@ export function PageTransition({
if (currentLayerEl) { if (currentLayerEl) {
gsap.set(currentLayerEl, { clearProps: 'transform,opacity,boxShadow' }); gsap.set(currentLayerEl, { clearProps: 'transform,opacity,boxShadow' });
} }
if (exitingLayerEl) {
gsap.set(exitingLayerEl, { clearProps: 'transform,opacity,boxShadow' });
}
}, },
}); });