Ich erstelle ein Next.js-Projekt mit Framer Motion für Seitenübergänge. Die alte Seite sollte aus ihrer aktuellen Bildlaufposition herausgleiten und die neue Seite sollte beginnend bei scrollTop = 0 hineingleiten.
Problem:
Nachdem ich auf der Startseite nach unten gescrollt habe und auf einen Übergangslink klicke, erscheint die neue Seite kurz an der alten Bildlaufposition, bevor sie nach oben springt. Ich möchte, dass es sofort oben beginnt, ohne dass ein sichtbarer Sprung auftritt.
Live-Reproduktion:
Minimale Codeausschnitte:
Code: Select all
'use client';
import React, { ReactNode } from 'react';
import Link, { LinkProps } from 'next/link';
import { MouseEventHandler } from 'react';
import { useRouter } from 'next/navigation';
interface TransitionLinkProps extends LinkProps {
children: ReactNode;
className?: string;
}
export default function TransitionLink({ href, children, className }: TransitionLinkProps) {
const router = useRouter();
const handleClick: MouseEventHandler = (e) => {
e.preventDefault();
router.push(href.toString(), { scroll: false });
};
return (
{children}
);
}
Code: Select all
'use client';
import React from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { usePathname } from 'next/navigation';
import { useContext, useRef, useEffect } from 'react';
import { LayoutRouterContext } from 'next/dist/shared/lib/app-router-context.shared-runtime';
function FrozenRouter(props: { children: React.ReactNode }) {
const context = useContext(LayoutRouterContext ?? {});
const frozen = useRef(context).current;
if (!frozen) return {props.children};
return (
{props.children}
);
}
export default function PageTransitionEffect({ children }: { children: React.ReactNode }) {
const pathname = usePathname();
return (
{
// Only reset scroll when the *enter* animation finishes
window.scrollTo(0, 0);
}}
>
{children}
);
}
Code: Select all
import type { Metadata } from 'next';
import '@/styles/reset.css';
import '@/app/globals.css';
import PageTransitionEffect from '@/components/PageTransitionEffect';
import Header from '@/components/Header';
export const metadata: Metadata = {
title: 'Create Next App',
description: 'Generated by create next app',
};
export default function RootLayout({
children,
}: Readonly) {
return (
{children}
);
}
useLayoutEffect(() => window.scrollTo(0,0))
onAnimationStart on motion div
Scrollen über Position einfrieren/unfreeze: behoben
scroll: false auf router.push und Link
Erwartetes Verhalten:
Alte Seite gleitet aus dem aktuellen Scroll heraus, neue Seite gleitet oben ohne sichtbaren Scrollsprung ein.
Frage:
Wie kann ich dafür sorgen, dass die neue Seite ihren Übergang sofort bei scrollTop = 0 beginnt, ohne dass sich dies auf die alte Seite auswirkt oder ein Sprung angezeigt wird?
Mobile version