如何让Framer Motion仅在initial与animate间循环动画,exit动画仅播放一次?
解决Framer Motion中AnimatePresence的无限循环exit动画问题
问题核心:当给组件的initial→animate过渡设置repeat: Infinity后,组件卸载时exit动画会继承这个重复属性,导致无限循环。之前用isLoading控制repeat的方式无效,是因为组件触发卸载流程时,状态更新无法及时覆盖过渡配置,且共用的过渡会让exit继承重复规则。
正确方案:为不同状态单独指定过渡配置
不要共用同一个transition属性,而是给animate状态单独设置无限重复的过渡,exit状态单独设置无重复的过渡。这样就能保证只有加载阶段的动画循环,卸载时只执行一次退出动画。
写法1:直接给exit指定exitTransition
<AnimatePresence> {isLoading && ( <motion.div initial={{ opacity: 0.5 }} animate={{ opacity: 0.8 }} // 仅initial到animate的过渡用无限重复 transition={{ repeatType: 'reverse', repeat: Infinity }} exit={{ opacity: 0 }} // exit动画单独配置,关闭重复 exitTransition={{ repeat: 0, duration: 0.3 }} // 可自定义退出动画时长 > {children} </motion.div> )} </AnimatePresence>
写法2:使用variants拆分状态配置
这种方式更清晰,适合复杂动画场景:
<AnimatePresence> {isLoading && ( <motion.div initial="initial" animate="animate" exit="exit" variants={{ initial: { opacity: 0.5 }, animate: { opacity: 0.8, transition: { repeatType: 'reverse', repeat: Infinity } }, exit: { opacity: 0, transition: { repeat: 0 } // 明确关闭重复 } }} > {children} </motion.div> )} </AnimatePresence>
原理说明
Framer Motion中,如果没有单独指定exitTransition或在variants中为exit状态设置过渡,exit动画会继承通用的transition配置。所以只要确保exit状态的过渡不包含repeat: Infinity,就能避免卸载时的无限循环。
内容的提问来源于stack exchange,提问作者basarat
相关产品推荐
相关产品推荐

