Next.js 13 页面跳转动画实现方法
要在 Next.js 13 中实现页面跳转动画,可以使用两种方法:
- 使用自定义 App 组件
在 pages 目录下创建一个名为 '_app.tsx' 的文件,并在其中定义一个自定义 App 组件。在该组件中,可以使用 Next.js 提供的 useRouter 和 useEffect 钩子来监听路由变化,并使用 CSS 动画实现页面跳转动画。例如:
import { AppProps } from 'next/app';
import { useRouter } from 'next/router';
import { useEffect, useState } from 'react';
import '../styles/globals.css';
function MyApp({ Component, pageProps }: AppProps) {
const router = useRouter();
const [isAnimating, setIsAnimating] = useState(false);
useEffect(() => {
const handleRouteChangeStart = () => {
setIsAnimating(true);
};
const handleRouteChangeComplete = () => {
setIsAnimating(false);
};
router.events.on('routeChangeStart', handleRouteChangeStart);
router.events.on('routeChangeComplete', handleRouteChangeComplete);
return () => {
router.events.off('routeChangeStart', handleRouteChangeStart);
router.events.off('routeChangeComplete', handleRouteChangeComplete);
};
}, [router]);
return (
<div className={`page-wrapper ${isAnimating ? 'animating' : ''}`}>
<Component {...pageProps} />
</div>
);
}
export default MyApp;
在上面的代码中,我们定义了一个名为 'isAnimating' 的状态来表示页面是否正在进行动画。在 useEffect 钩子中,我们使用 'router.events' 监听路由变化事件,当路由开始变化时,将 'isAnimating' 设置为 'true',当路由变化完成时,将其设置为 'false'。在组件返回的 JSX 中,我们使用 'isAnimating' 来控制页面的 CSS 类名,从而触发动画效果。
- 使用 Framer Motion 库
Framer Motion 是一个流行的动画库,可以帮助我们实现复杂的动画效果。在 Next.js 13 中,可以直接在页面组件中使用 Framer Motion 来实现页面跳转动画。例如:
import { motion } from 'framer-motion';
import { useRouter } from 'next/router';
import '../styles/globals.css';
function MyApp({ Component, pageProps }) {
const router = useRouter();
return (
<motion.div
key={router.route}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
>
<Component {...pageProps} />
</motion.div>
);
}
export default MyApp;
在上面的代码中,我们使用了 Framer Motion 提供的 'motion.div' 组件来包裹页面组件。在该组件中,我们使用 'initial' 属性来定义页面初始状态,'animate' 属性来定义页面动画结束状态,'exit' 属性来定义页面退出动画状态。当页面发生跳转时,Framer Motion 会自动根据这些状态来实现动画效果。需要注意的是,页面组件的 'key' 值必须与路由路径相同,这样 Framer Motion 才能正确地应用动画效果。
原文地址: https://www.cveoy.top/t/topic/nvT3 著作权归作者所有。请勿转载和采集!