使用 Framer-Motion 实现 Nextjs 页面过渡
创建流畅且引人入胜的页面过渡效果已成为提升用户体验的重要组成部分。流行的 React 框架 Next.js 与 React 的声明式动画库 Framer Motion 强强联合,为页面过渡注入活力,让我们开始吧。
设置项目
运行以下命令创建一个 Next.js 项目
npx create-next-app@latest
这将使用最新版本(我的版本是 14.1.0)启动 Next.js 项目。您可以根据自己的喜好设置 Next.js 项目,我将使用 TypeScript 和 App Router,并使用 Tailwind 进行样式设置。请清理app/page.tsxNext.js 起始页的根页面,我的页面如下所示。
app/page.tsx
export default function Home() {
return (
<section className="p-4">
<div className="container">
<h1 className="text-2xl font-bold">Home Page</h1>
<p className="w-1/2 font-medium py-2">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Molestias
natus minima exercitationem perferendis hic maxime nihil officia
fugit, illo asperiores fugiat odit harum, dicta cumque ad atque
assumenda! Saepe dolores repellendus animi harum ex voluptatibus
quaerat unde obcaecati quo consequuntur sequi, autem deleniti?
Eligendi ipsa impedit cupiditate accusantium delectus quidem.
</p>
</div>
</section>
);
}
另外,为了使动画看起来更简洁,我将添加两个内容相同的页面,app/about/page.tsx并app/contact/page.tsx添加一个页眉组件,以便在页面之间轻松导航header.tsx,并在布局中使用它。header.tsx
import Link from "next/link";
export default function Header() {
return (
<header>
<nav className="p-4">
<ul className="container flex gap-8">
<li>
<Link href="/">Home</Link>
</li>
<li>
<Link href="/about">About</Link>
</li>
<li>
<Link href="/contact">Contact</Link>
</li>
</ul>
</nav>
</header>
);
}
添加 Framer Motion
要安装 framer-motion,只需运行以下命令即可。
npm install framer-motion
安装完Framer-Motion后,我们将创建一个Transition.tsx组件来使用 Framer-Motion 定义页面基础过渡效果,以下是该组件的代码。
"use client";
import { motion } from "framer-motion";
export default function Transition({
children,
}: {
children: React.ReactNode;
}) {
return (
<motion.div
initial={{ y: 20, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
transition={{ ease: "easeInOut", duration: 0.75 }}
>
{children}
</motion.div>
);
}
如您所见,此组件是一个客户端组件,因此我们use client在组件声明顶部使用 `from` 将其标记为客户端组件,基本上我们使用` motioninitial` framer-motion、`animate` 和 `transition` 属性来定义页面动画。
使用 Nextjs 模板渲染动画页面
你可能会问,为什么我们不能像这样直接用组件Layout.tsx包裹我们的页面呢?Transition.tsx
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import Header from "./header";
import Transition from "./trasnition";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: "Page Transition",
description: "Using framer-motion to add trasition between pages",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body className={inter.className}>
<Header />
<Transition>{children}</Transition>
</body>
</html>
);
}
问题在于,你只能看到首次渲染(初始加载)时的动画,之后,如果你导航到其他页面,Next.js 不会重新渲染这些页面,layout因此过渡效果不会在这些页面上显示。所以,针对这种情况,`transition`就成了一个便捷的解决方案。以下是Next.js 文档中 ` Template.tsxtransition` 的定义。Template
与跨路由保持状态的布局不同,模板在导航时会为其每个子组件创建一个新的实例。这意味着当用户在共享同一模板的路由之间导航时,会挂载组件的新实例,DOM 元素会被重新创建,状态不会被保留,并且效果也会重新同步。
现在template.tsx在 app 目录下创建文件,复制粘贴组件中的代码Transition.tsx,并将组件名称重命名为 Template(),如下所示。
"use client";
import { motion } from "framer-motion";
export default function Template({ children }: { children: React.ReactNode }) {
return (
<motion.div
initial={{ y: 20, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
transition={{ ease: "easeInOut", duration: 0.75 }}
>
{children}
</motion.div>
);
}
好了!我们已经为项目添加了页面过渡效果,您可以根据自己的喜好自定义过渡效果,获得更好的体验。如有任何疑问,请随时提出。
文章来源:https://dev.to/joseph42a/nextjs-page-transition-with-framer-motion-33dg