GSAP收缩动画失效求助:FoodCard仅跨卡片收缩生效
解决GSAP动画在React卡片收缩时失效的问题
问题根源
核心是React的className样式与GSAP动画的时序冲突:
- 你在组件根元素的className中,直接根据
isExpanded状态设置了h-auto/h-64、w-auto/w-64,状态变化时React会立刻修改元素的宽高,完全覆盖GSAP的动画过程。 - 展开时,GSAP的
height:auto和React设置的h-auto目标一致,动画能正常执行;但收缩时,React会先把高度直接设为h-64(8rem),GSAP拿到的初始高度已经是目标值,自然看不到动画效果。 - 展开其他卡片后收缩当前卡片恢复正常,是因为其他组件的渲染触发了当前组件的重绘,此时GSAP能正确获取到展开状态下的实际高度,再执行收缩动画。
解决方案
方案1:移除className中的宽高控制,完全交由GSAP处理
先删掉className里的宽高相关条件判断,不让React直接控制元素尺寸:
// 原className // `${isExpanded ? "w-auto h-auto" : "w-64 h-64"}` // 修改后 `relative bg-gray-700 text-white rounded-lg shadow-md p-6 cursor-pointer hover:bg-gray-600 transition-all duration-300`
然后在GSAP动画中同时控制宽高:
useEffect(() => { if (isExpanded) { gsap.to(cardRef.current, { height: 'auto', width: 'auto', duration: 0.5, ease: 'linear' }); } else { gsap.to(cardRef.current, { height: '8rem', width: '16rem', // 对应原w-64的尺寸 duration: 0.5, ease: 'linear' }); } }, [isExpanded]);
方案2:使用useGSAP钩子优化时序
既然已经导入了@gsap/react,推荐用useGSAP替代useEffect,它能更好地和React生命周期同步,避免时序问题:
// 替换原useEffect代码 useGSAP(() => { gsap.to(cardRef.current, { height: isExpanded ? 'auto' : '8rem', width: isExpanded ? 'auto' : '16rem', duration: 0.5, ease: 'linear' }); }, [isExpanded]);
同样需要移除className中的宽高条件设置,避免样式冲突。
额外优化:确保auto高度计算精准
如果遇到height:auto动画不稳定的情况,可以手动计算展开状态的高度,再执行动画:
useGSAP(() => { const card = cardRef.current; if (isExpanded) { // 临时设置为auto获取真实高度,再重置为收缩状态高度,最后执行展开动画 const autoHeight = gsap.set(card, {height: 'auto'}).getProperty(card, 'height'); gsap.set(card, {height: '8rem'}); gsap.to(card, {height: autoHeight, duration: 0.5, ease: 'linear'}); } else { gsap.to(card, {height: '8rem', duration: 0.5, ease: 'linear'}); } }, [isExpanded]);
内容的提问来源于stack exchange,提问作者Kzich
相关产品推荐
相关产品推荐

