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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 15:41:45