如何去除Framer Motion中AnimatePresence的弹跳效果?
解决Framer Motion切换AnimatePresence元素时的弹跳问题
弹跳效果通常是因为动画使用了带弹性的默认缓动函数,或是动画参数、布局设置存在偏差,以下是几种可行的解决方法:
1. 替换默认缓动函数为非弹性类型
Framer Motion默认的缓动函数可能带有弹性效果,直接给动画状态指定线性或无弹性的缓动函数即可消除弹跳:
const variants = { enter: ({ direction, width }) => ({ x: direction * width, ease: "linear" // 也可使用"easeInOut"这类无弹性的缓动 }), center: { x: 0, ease: "linear" }, exit: ({ direction, width }) => ({ x: direction * -width, ease: "linear" }) };
2. 固定动画时长并统一参数
统一设置动画的时长,避免因默认时长差异导致的视觉跳动,同时确保所有状态的动画参数一致:
const variants = { enter: ({ direction, width }) => ({ x: direction * width, ease: "linear", duration: 0.3 // 根据需求调整时长 }), center: { x: 0, ease: "linear", duration: 0.3 }, exit: ({ direction, width }) => ({ x: direction * -width, ease: "linear", duration: 0.3 }) };
3. 确认布局参数的准确性
检查custom属性中传递的width值是否为元素的实际宽度,避免因宽度计算错误导致动画起始/结束位置偏移:
- 如果使用Tailwind的
w-full,确保父容器宽度固定,无动态变化 - 可通过
useRef获取元素实际宽度后传入,而不是直接使用父容器宽度:
const elementRef = useRef(null); const [width, setWidth] = useState(0); useEffect(() => { if (elementRef.current) { setWidth(elementRef.current.offsetWidth); } }, []); // 然后在custom中传入width <motion.div ref={elementRef} key={index} variants={variants} initial="enter" animate="center" exit="exit" custom={{ direction, width }} w="full" > // 内容 </motion.div>
4. 禁用动画的惯性效果
如果以上方法无效,可尝试给motion元素加上transition={{ type: "tween" }},强制使用补间动画而非弹簧动画:
<motion.div key={index} variants={variants} initial="enter" animate="center" exit="exit" custom={{ direction, width }} w="full" transition={{ type: "tween" }} > // 内容 </motion.div>
内容的提问来源于stack exchange,提问作者GʀᴜᴍᴘʏCᴀᴛ
相关产品推荐
相关产品推荐

