Framer Motion Animate Presence数字切换动画异常问题求助
解决数字切换时的上下滑入滑出动画问题
核心问题分析
你遇到的两个问题根源在于:
- 数字并排显示:新旧数字元素默认是流式布局,没有重叠定位,导致切换时短暂共存并排列
- 绝对定位后旧数字无法退出:缺少容器裁剪、动画触发时机控制,或者动画状态未正确绑定
修复方案
1. CSS样式调整
首先设置容器的固定尺寸与溢出裁剪,确保数字元素在容器内切换:
/* 数字容器:固定尺寸+相对定位,作为绝对定位元素的参照 */ .counter-container { position: relative; width: 60px; height: 80px; overflow: hidden; /* 裁剪超出容器的数字部分 */ } /* 数字元素基础样式:绝对定位实现重叠 */ .counter-digit { position: absolute; top: 0; left: 0; right: 0; bottom: 0; display: flex; align-items: center; justify-content: center; font-size: 48px; transition: transform 0.3s ease-in-out; /* 统一过渡动画 */ } /* 旧数字退出动画:向下移出容器 */ .counter-digit.exit { transform: translateY(100%); } /* 新数字进入动画:从上方移入容器 */ .counter-digit.enter { transform: translateY(-100%); } /* 激活状态:数字处于容器中心 */ .counter-digit.active { transform: translateY(0); }
2. React组件逻辑修改
通过临时保留旧数字、监听动画时长来控制DOM元素的生命周期,确保动画完整执行:
import { useState, useEffect } from 'react'; import './styles.css'; export default function App() { const [count, setCount] = useState(0); // 临时存储旧数字,用于渲染退出动画 const [prevCount, setPrevCount] = useState<number | null>(null); // 动画结束后清除旧数字 useEffect(() => { if (prevCount !== null && prevCount !== count) { const timer = setTimeout(() => setPrevCount(null), 300); return () => clearTimeout(timer); } }, [count, prevCount]); const handleIncrement = () => { // 先保存当前数字作为旧值,再更新新数字 setPrevCount(count); setCount(prev => prev + 1); }; return ( <div className="App"> <div className="counter-container"> {/* 渲染旧数字并添加退出动画类 */} {prevCount !== null && ( <span className="counter-digit exit"> {prevCount} </span> )} {/* 渲染新数字:切换时先执行进入动画,再回到激活状态 */} <span className={`counter-digit ${prevCount !== null ? 'enter active' : 'active'}`}> {count} </span> </div> <button onClick={handleIncrement}>Increment</button> </div> ); }
关键细节说明
overflow: hidden:确保数字移出容器时被裁剪,不会显示多余部分- 绝对定位:让新旧数字完全重叠,避免并排显示
- 动画时序:通过
setTimeout匹配动画时长,确保旧数字的退出动画完成后再移除DOM元素 - 状态控制:用
prevCount临时保存旧值,触发动画流程,动画结束后重置为null清理DOM
内容的提问来源于stack exchange,提问作者Kaleb Schmottlach
相关产品推荐
相关产品推荐

