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; }
方案说明
- 把动画延迟逻辑完全交给CSS控制,避免React状态更新与动画时序的冲突。
- 给收起状态也设置了递减的延迟,确保菜单收起时图标也逐个隐藏,同时重置动画状态,下次展开时能重新触发完整的逐个显示效果。
- 明确指定
transition的属性(transform和opacity),避免不必要的属性过渡,提升动画稳定性。
内容的提问来源于stack exchange,提问作者user20743344
相关产品推荐
相关产品推荐

