TweenMax在React组件中动画不执行是怎么回事?

极客薪羽 阅读 42

我在React里用TweenMax给一个div加淡入动画,但页面加载后元素直接显示,完全没有动画效果。控制台也没报错,我试过把动画逻辑放到useEffect里,也检查了ref是否正确绑定,但就是不动。

是不是哪里写错了?下面是我的代码:

import { useEffect, useRef } from 'react';
import { gsap } from 'gsap';

export default function FadeInBox() {
  const boxRef = useRef(null);

  useEffect(() => {
    gsap.from(boxRef.current, { opacity: 0, duration: 1 });
  }, []);

  return <div ref={boxRef} style={{ width: '100px', height: '100px', background: 'red' }} />;
}
我来解答 赞 4 收藏
二维码
手机扫码查看
2 条解答
南宫艳平
问题很简单,你的元素初始opacity就是1,gsap.from是从你指定的值开始动画到当前状态,但你没告诉它初始状态应该是什么样的。

改一下,用 fromTo 或者直接在DOM上设置初始opacity:

方案一:用 fromTo 明确指定起始状态

useEffect(() => {
gsap.fromTo(boxRef.current,
{ opacity: 0 },
{ opacity: 1, duration: 1 }
);
}, []);


方案二:直接在style里设初始opacity为0

return (
ref={boxRef}
style={{
width: '100px',
height: '100px',
background: 'red',
opacity: 0
}}
/>
);


然后用 from 就行:

useEffect(() => {
gsap.to(boxRef.current, { opacity: 1, duration: 1 });
}, []);


顺带提一下,如果你用的是React 18开发模式,StrictMode会让useEffect跑两遍,可能导致动画看起来怪怪的。如果有这个问题,可以加个ref标记来防止重复执行:

const hasAnimated = useRef(false);

useEffect(() => {
if (hasAnimated.current) return;
hasAnimated.current = true;

gsap.fromTo(boxRef.current,
{ opacity: 0 },
{ opacity: 1, duration: 1 }
);
}, []);
点赞 1
2026-03-10 21:11
司马康佳
啊这个问题我踩过坑!你的代码看起来没问题,但忽略了一个关键点 - React的初始渲染和GSAP动画的时机问题。

问题出在组件第一次渲染时,ref还没绑定到DOM元素上。虽然你用了useEffect的空依赖数组,但这时候boxRef.current可能还是null。我之前也被这个坑折磨了半小时...

试试这样改:

useEffect(() => {
if (boxRef.current) {
gsap.from(boxRef.current, {
opacity: 0,
duration: 1,
// 再加个这个保险点
immediateRender: false
});
}
}, []);


关键改动:
1. 加个if判断确保ref存在
2. 设置immediateRender:false防止初始渲染闪烁

另外,如果元素初始样式有opacity:1,动画也会失效。所以要么初始CSS设opacity:0,要么像上面代码这样强制从0开始。
点赞
2026-03-09 13:01