reactjs - 在 Framer Motion 中不起作用的子项的退出动画
问题描述
我正在使用 Framer Motion 在 React 中制作汉堡菜单动画。当我点击汉堡菜单时,侧边抽屉和导航项从左侧滑入。
当我单击关闭菜单图标时,整个侧抽屉滑到左侧(这意味着 SideDrawer 组件上的退出道具正在工作)。
我想要什么? 当我单击关闭图标时,我希望导航项先滑出,然后再滑出侧抽屉。我尝试将退出道具添加到儿童导航项。但它不起作用。
我怎样才能达到预期的效果?
代码片段如下:
src/App.js
import React, { useState } from "react";
import "./App.css";
import Menu from "./components/Menu";
import SideDrawer from "./components/SideDrawer";
import Overlay from "./components/Overlay";
const App = () => {
const [menuOpen, setMenuOpen] = useState(false);
const handleMenuClick = () => {
setMenuOpen(!menuOpen);
};
return (
<div className="App">
<Menu menuOpen={menuOpen} onMenuClick={handleMenuClick} />
<SideDrawer menuOpen={menuOpen} />
<Overlay menuOpen={menuOpen} />
</div>
);
};
export default App;
src/components/Menu.js
import React, { useState } from "react";
import { motion } from "framer-motion";
const lineOneVariants = {
initial: { rotate: "0deg" },
animate: { y: ".8rem", rotate: "45deg", transformOrigin: "center center" },
};
const lineTwoVariants = {
initial: { opacity: 1 },
animate: { opacity: 0 },
};
const lineThreeVariants = {
initial: { rotate: "0deg" },
animate: { y: "-.8rem", rotate: "-45deg", transformOrigin: "center center" },
};
const Menu = ({ onMenuClick, menuOpen }) => {
return (
<div className="hamburger_menu">
<div className="hamburger_menu-line-container" onClick={onMenuClick}>
<motion.div
variants={lineOneVariants}
initial="initial"
animate={menuOpen ? "animate" : "initial"}
className="hamburger_menu-line-1"
></motion.div>
<motion.div
variants={lineTwoVariants}
initial="initial"
animate={menuOpen ? "animate" : "initial"}
className="hamburger_menu-line-2"
></motion.div>
<motion.div
variants={lineThreeVariants}
initial="initial"
animate={menuOpen ? "animate" : "initial"}
className="hamburger_menu-line-3"
></motion.div>
</div>
</div>
);
};
export default Menu;
src/components/Overlay.js
import React from "react";
import { motion } from "framer-motion";
const overlayVariants = {
initial: { opacity: 0 },
animate: { opacity: 1 },
};
const Overlay = ({ menuOpen }) => {
return (
<motion.div
variants={overlayVariants}
initial="initial"
animate={menuOpen ? "animate" : "initial"}
className="overlay"
></motion.div>
);
};
export default Overlay;
src/components/SideDrawer.js
import React from "react";
import { motion, AnimatePresence } from "framer-motion";
const drawerVariants = {
initial: {
x: "-100vw",
opacity: 0,
},
animate: {
x: 0,
opacity: 1,
transition: {
type: "linear",
ease: "easeInOut",
staggerChildren: 0.1,
delayChildren: 0.15,
},
},
};
const drawerMenuVariants = {
initial: { x: "-5rem", opacity: 0 },
animate: {
x: 0,
opacity: 1,
transition: {
type: "linear",
ease: "easeInOut",
},
},
};
const SideDrawer = ({ menuOpen }) => {
return (
<AnimatePresence>
{menuOpen && (
<motion.div
variants={drawerVariants}
initial="initial"
animate="animate"
exit="initial"
className="sideDrawer"
>
<nav className="sideDrawer-menu">
<ul>
<motion.li
variants={drawerMenuVariants}
whileHover={{ scale: 1.05 }}
>
<a href="#">Register/Login</a>
</motion.li>
<motion.li
variants={drawerMenuVariants}
whileHover={{ scale: 1.05 }}
>
<a href="#">About</a>
</motion.li>
<motion.li
variants={drawerMenuVariants}
whileHover={{ scale: 1.05 }}
>
<a href="#">Projects</a>
</motion.li>
<motion.li
variants={drawerMenuVariants}
whileHover={{ scale: 1.05 }}
>
<a href="#">CV</a>
</motion.li>
</ul>
</nav>
</motion.div>
)}
</AnimatePresence>
);
};
export default SideDrawer;
解决方案
您需要告诉侧抽屉等到孩子的退出动画完成,然后再开始自己的退出动画。
您可以通过使用when
. transition
请参阅文档中的编排。
在您的情况下,您会将其添加到initial
您的变体中drawerVariants
,因为这是您在退出时设置动画的变体:
initial: {
x: "-100vw",
opacity: 0,
transition: {
when: "afterChildren"
}
},
如果你想在行为中反映动画,你可能还想在那里添加一些惊人的和缓动,但我会留给你。
推荐阅读
- android - 错误您需要将 Theme.AppCompat 主题(或后代)与活动一起使用
- cluster-computing - 如何子到和监控 VerneMQ 集群?
- javascript - 如何在 Angular 和 RxJs 中管理多个顺序订阅方法?
- javascript - 您必须指定 'to' 属性
- groovy - 带有委托和动态参数的 Groovy 闭包
- python - PyQt5:将 QLineEdit 与 QFileDialog 绑定
- c# - 并发任务和每个任务的不同光标位置
- excel - 我将如何摆脱此错误消息?
- android - 当所有数据都由运行时的直接用户输入提供时,使用 LiveData 有什么好处?
- c# - protobuf 包是如何使用的?