使用 Framer Motion 重新混合运行页面过渡动画

发布于 2025-01-18 04:45:10 字数 953 浏览 3 评论 0原文

我想向我的网络应用程序添加一些页面转换。 问题是退出动画不起作用。

我有一个 Motion 组件

// app/components/Motion.tsx    
import React from "react";
import { motion } from "framer-motion";
export default function Motion(props: {
  children: React.ReactChild | React.ReactFragment | React.ReactPortal;
}) {
  return (
    <motion.div
      className="w-full h-screen bg-blue-400 flex pt-24 mx-auto"
      initial={{ opacity: 0, x: -100 }}
      animate={{ opacity: 1, x: 0 }}
      exit={{ opacity: 0, x: -100 }}
      transition={{ duration: 2 }}
    >
      {props.children}
    </motion.div>
  );
}

,我想在其中包装每个页面,如下所示:

// app/routes/contact.tsx
import Motion from "~/components/Motion";

export default function contact() {
  return (
    <Motion>
      <div>Contact</div>
    </Motion>
  );
}

我知道我应该使用 framer-motion 中的 但我不知道在哪里。

I would like to add some page transitions to my web app.
The problem is that the exit animation doesn't work.

I have a Motion Component

// app/components/Motion.tsx    
import React from "react";
import { motion } from "framer-motion";
export default function Motion(props: {
  children: React.ReactChild | React.ReactFragment | React.ReactPortal;
}) {
  return (
    <motion.div
      className="w-full h-screen bg-blue-400 flex pt-24 mx-auto"
      initial={{ opacity: 0, x: -100 }}
      animate={{ opacity: 1, x: 0 }}
      exit={{ opacity: 0, x: -100 }}
      transition={{ duration: 2 }}
    >
      {props.children}
    </motion.div>
  );
}

In which I want to wrap every page like this:

// app/routes/contact.tsx
import Motion from "~/components/Motion";

export default function contact() {
  return (
    <Motion>
      <div>Contact</div>
    </Motion>
  );
}

I know that I should use the <AnimatePresence> from framer-motion but I don't know where.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

葬花如无物 2025-01-25 04:45:10

有趣的是,我只是想弄清楚几个小时前的方法。我是Remix的新手,但这是一个非常简单的示例,说明了我为了使路线动画工作的工作所做的工作。

  1. root.jsx
import {
  Links,
  LiveReload,
  Meta,
  Outlet,
  Scripts,
  ScrollRestoration,
} from 'remix'

import { AnimatePresence } from 'framer-motion'

import styles from './styles/app.css'

export function meta() {
  return {
    charset: 'utf-8',
    title: 'New Remix App',
    viewport: 'width=device-width,initial-scale=1',
  }
}

export function links() {
  return [{ rel: 'stylesheet', href: styles }]
}

export default function App() {
  return (
    <html lang="en">
      <head>
        <Meta />
        <Links />
      </head>
      <body>
        <AnimatePresence exitBeforeEnter>
          <Outlet />
        </AnimatePresence>
        <ScrollRestoration />
        <Scripts />
        <LiveReload />
      </body>
    </html>
  )
}
  1. 第一路由的示例index.jsx
import { motion } from 'framer-motion'

export default function Index() {
  return (
        <motion.div
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
          transition={{ duration: 0.5 }}
          className="w-full h-full md:col-span-3 sm:overflow-auto relative z-0"
        >

               {/* page content */}

        </motion.div>
  1. same &lt; motion.div&gt;&lt;&lt;&lt;&lt;&lt;&lt; dov&ggt; parth tos to to to上述将其应用于下一个路由(例如大约.jsx) - 包括相同的初始,动画,退出和过渡属性。

Funny enough, I was just trying to figure out how to do this a few hours ago. I'm super new to Remix, but here's a really simple example of what I did to get route animations working.

  1. root.jsx
import {
  Links,
  LiveReload,
  Meta,
  Outlet,
  Scripts,
  ScrollRestoration,
} from 'remix'

import { AnimatePresence } from 'framer-motion'

import styles from './styles/app.css'

export function meta() {
  return {
    charset: 'utf-8',
    title: 'New Remix App',
    viewport: 'width=device-width,initial-scale=1',
  }
}

export function links() {
  return [{ rel: 'stylesheet', href: styles }]
}

export default function App() {
  return (
    <html lang="en">
      <head>
        <Meta />
        <Links />
      </head>
      <body>
        <AnimatePresence exitBeforeEnter>
          <Outlet />
        </AnimatePresence>
        <ScrollRestoration />
        <Scripts />
        <LiveReload />
      </body>
    </html>
  )
}
  1. Example of first route index.jsx
import { motion } from 'framer-motion'

export default function Index() {
  return (
        <motion.div
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
          transition={{ duration: 0.5 }}
          className="w-full h-full md:col-span-3 sm:overflow-auto relative z-0"
        >

               {/* page content */}

        </motion.div>
  1. Same <motion.div></motion.div> parent elements as above to be applied to the next route (e.g. about.jsx) - including the same initial, animate, exit, and transition attributes.
箹锭⒈辈孓 2025-01-25 04:45:10

您可以在“root.tsx”文件中尝试此操作。

     <AnimatePresence mode="wait">
      <motion.div
        key={useLocation().pathname}
        variants={{
          initial: { opacity: 0, y: -1000 },
          animate: { opacity: 1, y: 0 },
          exit: { opacity: 1, y: 1000 },
        }}
        initial="initial"
        animate="animate"
        exit="exit"
      >
        <Outlet />
      </motion.div>

请注意“mode”属性而不是 exitBeforeEnter(已弃用)。

还要注意孩子身上的关键支柱。

希望这有帮助。

You can try this out at the “root.tsx” file.

     <AnimatePresence mode="wait">
      <motion.div
        key={useLocation().pathname}
        variants={{
          initial: { opacity: 0, y: -1000 },
          animate: { opacity: 1, y: 0 },
          exit: { opacity: 1, y: 1000 },
        }}
        initial="initial"
        animate="animate"
        exit="exit"
      >
        <Outlet />
      </motion.div>

Please note the “mode” prop instead of exitBeforeEnter (deprecated).

And also notice the key prop in the child.

Hope this helps. ????

Source: fixtergeek.com

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文