Framer Motion子元素stagger动画失效问题求助
Framer Motion父元素Stagger动画不生效的解决方案
核心问题分析
你的代码里有两个关键问题导致父元素的stagger配置失效:
- 子元素手动声明了
initial="initial"和animate="open",完全脱离了父元素的变体控制,父元素的stagger规则无法传递给子元素 - 父元素未配置
exit状态,关闭时的反向stagger效果无法触发
具体修改步骤
移除子元素的手动initial/animate属性
子元素只需要绑定variants,让父元素统一控制动画状态,这样父元素的stagger配置才能生效:// 原代码 <motion.div key={index} variants={childVars} initial="initial" animate="open" > // 修改后 <motion.div key={index} variants={childVars} >给父元素补充exit变体配置
为父元素的parentVars添加exit状态,实现关闭时的反向stagger效果:const parentVars = { initial: { transition: { staggerChildren: 0.2, staggerDirection: -1 } }, open: { transition: { delayChildren: 0.3, staggerChildren: 0.2, staggerDirection: 1 } }, exit: { transition: { staggerChildren: 0.15, staggerDirection: -1 } } };同步父元素的exit状态绑定
把父级motion.div的exit属性改为"exit",对应上面新增的变体:<motion.div className="flex flex-col items-center justify-center h-full" variants={parentVars} initial="initial" animate="open" exit="exit" >优化菜单容器的动画时序
给menuVars添加透明度动画,并调整过渡参数,让菜单高度变化和子元素动画更协调:const menuVars = { initial: { height: 0, opacity: 0 }, animate: { height: "15rem", opacity: 1, transition: { duration: 0.5, ease: "easeOut" } }, exit: { height: 0, opacity: 0, transition: { duration: 0.5, ease: "easeIn", delayChildren: 0.3 } } };
修改后的完整代码
import { useState } from "react"; import CarouselP1 from "../carousel/carouselP1"; import { MdKeyboardDoubleArrowDown } from "react-icons/md"; import { MdKeyboardDoubleArrowUp } from "react-icons/md"; import { motion, AnimatePresence } from "framer-motion"; const ProjectCard1 = ({ images }) => { const [expanded, setExpanded] = useState(false); const handleExpand = () => { setExpanded(!expanded); }; const details = [ { text: "afafcacascasc" }, { text: "adasdascasc" }, { text: "afafcacawfgwefaEDFAscasc" }, { text: "afafcaE5TWERWEcascasc" }, { text: "DFWEQFEAFA" }, { text: "HRTHDGDRG" }, ]; const menuVars = { initial: { height: 0, opacity: 0 }, animate: { height: "15rem", opacity: 1, transition: { duration: 0.5, ease: "easeOut" } }, exit: { height: 0, opacity: 0, transition: { duration: 0.5, ease: "easeIn", delayChildren: 0.3 } } }; const parentVars = { initial: { transition: { staggerChildren: 0.2, staggerDirection: -1 } }, open: { transition: { delayChildren: 0.3, staggerChildren: 0.2, staggerDirection: 1 } }, exit: { transition: { staggerChildren: 0.15, staggerDirection: -1 } } }; const childVars = { initial: { y: "30vh", transition: { duration: 0.5 } }, open: { y: 0, transition: { duration: 0.7 } }, exit: { y: "30vh", transition: { duration: 0.5 } } }; return ( <div className="flex items-center justify-center flex-col space-y-3"> <CarouselP1 images={images} /> <div className="flex flex-col items-center justify-center w-96 max-w-80"> <p>WEGdrfbxcvb</p> </div> <button className="flex items-center justify-center cursor-pointer" onClick={handleExpand} > <span className="pr-2">Details</span> {expanded ? ( <MdKeyboardDoubleArrowUp className="mt-1" /> ) : ( <MdKeyboardDoubleArrowDown className="mt-1" /> )} </button> <AnimatePresence> {expanded && ( <motion.div variants={menuVars} initial="initial" animate="animate" exit="exit" className="flex rounded-lg items-center h-[15rem] justify-center w-48 bg-sky-200 my-2 origin-top overflow-hidden" > <motion.div className="flex flex-col items-center justify-center h-full" variants={parentVars} initial="initial" animate="open" exit="exit" > {details.map((item, index) => ( <div className="overflow-hidden" key={index}> <motion.div variants={childVars}> {item.text} </motion.div> </div> ))} </motion.div> </motion.div> )} </AnimatePresence> <button className="w-18 h-10 p-2 bg-sky-400 rounded-lg"> <a href="">Source Code</a> </button> </div> ); }; export default ProjectCard1;
内容的提问来源于stack exchange,提问作者MH_Rabea
相关产品推荐
相关产品推荐

