在Next.js 16.2.6和 Framer Motion 12.4.0下,退出动画不起作用
我正在使用Framer Motion v12.40.0尝试为每个页面实现页面切换过渡。我的目标是当用户点击导航栏中的链接时,当前页面先执行退出动画,然后跳转到下一页。
但我遇到了一个问题:退出动画不起作用,只有进入动画起作用。
我的思路是写一个animate包装器,然后将其应用到每个页面。
以下是导航栏的完整代码:
import Link from 'next/link'
export default function Navbar() {
return (
<nav className="bg-orange-950 text-gray-50 p-4 shadow-md">
<div className="container mx-auto flex justify-between items-center">
<Link href="/" className="text-xl font-bold">
Company Logo
</Link>
<div className="space-x-6">
<Link href="/" className="hover:text-lime-600 transition">
Home
</Link>
<Link href="/services" className="hover:text-lime-600 transition">
Services
</Link>
<Link href="/pricing" className="hover:text-lime-600 transition">
Pricing
</Link>
<Link href="/about" className="hover:text-lime-600 transition">
About
</Link>
<Link href="/contact" className="hover:text-lime-600 transition">
Contact
</Link>
</div>
</div>
</nav>
)
}
以下是 layout.tsx 的完整代码:
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import Navbar from '@/components/Navbar'
import Footer from '@/components/Footer'
import './globals.css'
const inter = Inter({ subsets: ['latin'] })
export const metadata: Metadata = {
title: 'Company Website',
description: 'Welcome to our company website',
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body className={inter.className}>
<div className="min-h-screen flex flex-col">
<Navbar />
<main className="w-full">
{children}
</main>
<Footer />
</div>
</body>
</html>
)
}
以下是客户端组件中animate包装器的完整代码:
'use client';
import { motion, AnimatePresence } from 'framer-motion';
import { usePathname } from "next/navigation";
export default function AnimateWrapper({ children }: { children: React.ReactNode }) {
const pathname = usePathname();
return (
<AnimatePresence mode="wait">
<motion.div
key={pathname}
initial={{ opacity: 0, scale: 0.95, x:-1000 }}
animate={{ opacity: 1, scale: 1, x:0 }}
exit={{ opacity: 0, scale: 0.95, y:100 }}
transition={{ duration: 0.7, ease: [0.25, 0.1, 0.25, 1] }}
>
{children}
</motion.div>
</AnimatePresence>
);
}
以下是首页的完整代码,我将animate包装器应用到包括首页在内的每段代码:
import AnimateWrapper from '@/components/AnimateWrapper';
export default function Home() {
return (
<AnimateWrapper>
<div className="w-full justify-items-center p-10 min-h-[calc(100vh-8rem)] bg-green-950 text-blue-100">
<h1 className="text-4xl font-bold mb-6">Welcome to our company</h1>
<div className="text-lg">
...
</div>
</div>
</AnimateWrapper>
)
}
我已经阅读了官方文档,animate包装器中的motion.div标签需要一个key属性来启用退出动画,但我不知道key属性应使用的正确值,或者是否还缺少什么。
先感谢你们提供的任何解决方案和回答。
解决方案
根本原因在于Next.js App路由架构与传统页面路由相比已发生了根本变化。
有两种可能有帮助的方法。
第一种方法是把你的Next.js项目切换回使用传统的页面路由并重新启动。
Next.js仍然允许用户在最新版本中选择页面路由。
如果你坚持使用App路由,那么有一个名为next-transition-router的库。
https://github.com/ismamz/next-transition-router
下面是我在GitHub仓库中的测试网站。
https://github.com/robin-artemstein/nextjs-company-website-framer-motion
祝你好运。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。