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

React动画不一致问题求助:菜单图标逐次显示异常

问题:快速点击菜单按钮时图标提前显示异常

我实现了一个点击按钮带动画展开的菜单,要求菜单内的图标逐个依次显示。目前功能基本完成,但快速点击“+”按钮时会出现异常:第二次打开菜单时,最右侧的两个图标已提前显示,不符合逐个显示的要求。

相关代码

React组件

const AnimatedActionMenu = (props) => {
  let [active, setActive] = React.useState(false);
  return (
    <div className="animated-action-menu">
      <div className={active ? 'container active' : 'container'}>
        <div className="menu">
          <div className="menu-item" style={{ transitionDelay: '1s' }}>
            <DingdingOutlined />
          </div>
          <div className="menu-item" style={{ transitionDelay: '1.5s' }}>
            <TwitterOutlined />
          </div>
          <div className="menu-item" style={{ transitionDelay: '2s' }}>
            <GoogleOutlined />
          </div>
        </div>
        <div
          className="toggle"
          onClick={() => {
            setActive(!active);
          }}
        ></div>
      </div>
    </div>
  );
};

CSS

html,
body,
#root {
  height: 100%;
}

.animated-action-menu {
  display: flex;
  background-color: goldenrod;
  justify-content: center;
  align-items: center;
  height: 100%;
}

.animated-action-menu .container {
  position: relative;
  z-index: 1;
}

/* Toggle related animations */
.animated-action-menu .container .toggle {
  background: white;
  border-radius: 50%;
  height: 72px;
  width: 72px;
  cursor: pointer;
  display: flex;
  justify-content: center;
  align-items: center;
}
.animated-action-menu .container .toggle:before {
  content: '+';
  font-size: 32px;
  transition: transform 1.5s;
}
.animated-action-menu .container.active .toggle:before {
  transform: rotate(225deg);
}

/* Menu related animations */
.animated-action-menu .container .menu {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  height: 16px;
  width: 16px;
  background-color: red;
  transition: transform 0.5s, width 0.5s, height 0.5s;
  transition-delay: 1s, 0.5s, 0.5s;
  border-radius: 100px;
  z-index: -1;
  display: flex;
  justify-content: space-around;
  align-items: center;
  gap: 1px;
}

.animated-action-menu .container.active .menu {
  position: absolute;
  z-index: 1;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -150px);
  height: 80px;
  width: 250px;
  transition-delay: 0s, 0.5s, 0.5s;
}

/* Menu item animations */
.animated-action-menu .container .menu .menu-item {
  transition: 1s;
  transform: translateY(-30px);
  opacity: 0;
}

.animated-action-menu .container.active .menu .menu-item {
  transform: translateY(0px);
  opacity: 1;
}

问题原因

直接在JSX的style属性中设置transitionDelay会导致动画时序与React状态更新不同步。当快速切换菜单状态时,部分菜单项的动画状态没有被正确重置,导致再次展开时跳过了延迟直接显示。

解决方案

将菜单项的延迟逻辑移到CSS中,通过.active类分别控制展开和收起状态的动画延迟,确保每次状态切换时动画都能从头触发。

修改后的React组件

移除JSX中style属性的transitionDelay,给每个菜单项添加独立类名:

const AnimatedActionMenu = (props) => {
  let [active, setActive] = React.useState(false);
  return (
    <div className="animated-action-menu">
      <div className={active ? 'container active' : 'container'}>
        <div className="menu">
          <div className="menu-item item-1">
            <DingdingOutlined />
          </div>
          <div className="menu-item item-2">
            <TwitterOutlined />
          </div>
          <div className="menu-item item-3">
            <GoogleOutlined />
          </div>
        </div>
        <div
          className="toggle"
          onClick={() => {
            setActive(!active);
          }}
        ></div>
      </div>
    </div>
  );
};

修改后的CSS(菜单项动画部分)

/* Menu item animations */
.animated-action-menu .container .menu .menu-item {
  transition: transform 1s, opacity 1s;
  transform: translateY(-30px);
  opacity: 0;
}

/* 展开时的逐个显示延迟 */
.animated-action-menu .container.active .menu .item-1 {
  transition-delay: 1s;
}
.animated-action-menu .container.active .menu .item-2 {
  transition-delay: 1.5s;
}
.animated-action-menu .container.active .menu .item-3 {
  transition-delay: 2s;
}

/* 收起时的逐个隐藏延迟(重置动画状态) */
.animated-action-menu .container .menu .item-1 {
  transition-delay: 0s;
}
.animated-action-menu .container .menu .item-2 {
  transition-delay: 0.2s;
}
.animated-action-menu .container .menu .item-3 {
  transition-delay: 0.4s;
}

方案说明

  1. 把动画延迟逻辑完全交给CSS控制,避免React状态更新与动画时序的冲突。
  2. 给收起状态也设置了递减的延迟,确保菜单收起时图标也逐个隐藏,同时重置动画状态,下次展开时能重新触发完整的逐个显示效果。
  3. 明确指定transition的属性(transform和opacity),避免不必要的属性过渡,提升动画稳定性。

内容的提问来源于stack exchange,提问作者user20743344

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 13:55:20