You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何去除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ᴀᴛ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 20:43:29