这次我们将学习如何使用GSAP库与React Js一起制作动画。
注意:这不是GSAP教程,因此您必须对此库有一些概念。
目的是您知道如何与React JS生态系统中的动画相辅相成。
目录。
ðTechnologies to be used.
ðCreating the project.
ðUsing GSAP for the first time.
ðGetting to know gsap.context().
ðUsing Timelines.
ðAnimating with interactions.
ðAvoiding flash of content that is not yet styled.
ð Conclusion.
要使用的技术。
- ¶ï标JS(v.18)
- â¶ï¸ GSAP 3
- - vite js
- â¶istypript
- ¶ï走CSS香草(您可以在本文结尾处的存储库中找到样式)
创建项目。
我们将命名项目: gsap-react
(可选,您可以随心所欲地命名)。
npm init vite@latest
我们使用Vite JS创建项目,然后选择与打字稿进行选择。
然后,我们运行以下命令来导航到刚创建的目录。
cd gsap-react
然后我们安装依赖项。
npm install
然后我们在代码编辑器中打开项目(在我的情况下与代码)。
code .
第一次使用GSAP。
在 src/app.tsx 文件中,我们删除所有内容并创建一个用hello world
显示DIV的组件。
标题组件并不那么重要。
const App = () => {
return (
<>
<Title />
<div className="square">Hello World</div>
</>
)
}
export default App
这就是它的外观。
现在让我们安装GSAP。
npm install gsap
使用 gsap 并为某些元素进行动画,我们可以以下面的方式进行...
首先,我们导入 gsap 。
然后,GSAP具有多个可以执行动画的功能。
- to :将从元素的当前状态开始,并朝向插值中定义的值。
- 来自:就像一个反向.to(),它从插值中定义的值和以元素的当前状态结束。
- 从 :定义初始值和最终值。
- set *:立即设置属性(无动画)。
在这种情况下,我们将使用最常见的 to 函数,因为所有函数均以两个参数的方式使用(除了接收3)。
。-
第一个参数是要动画的元素或元素,该参数可以是字符串(HTML元素的ID甚至复杂的CSS选择器),也可以是HTML元素或HTML元素的数组。
-
第二个参数是一个对象,带有您要动画的变量以及要给它们的值。
import { gsap } from "gsap";
const App = () => {
gsap.to( ".square", { rotate: 360 })
return (
<>
<div className="square">Hello World</div>
</>
)
}
export default App
但是停止,您刚刚看到的是ReactJSð....
的不良习惯。
首先,诸如动画之类的副作用应在使用效果挂钩内部执行,以避免出乎意料的行为。
第二,请注意,我们放置的第一个参数“。square” ,这还不错,它甚至可以正常工作,但是,React建议我们不要以这种方式访问DOM元素,为此我们将使用另一个钩子,即 useref 。
那么,这将是我们的第一个动画的代码,当应用程序启动时,将执行动画,并且应该以360度的速度与Hello World一起旋转。
import { gsap } from "gsap";
import { useEffect, useRef } from "react";
const App = () => {
const app = useRef<HTMLDivElement>(null);
useEffect(() => {
gsap.to(app.current, { rotate: 360, duration: 5 })
}, [])
return (
<>
<div ref={app}>Hello World</div>
</>
)
}
export default App
â€了解gsap.context()。
好吧,我们已经看到了如何使用良好实践来制作动画。但是,如果我们想为不同的元素制作其他动画,我们是否必须创建更多的参考?好吧,这不是必需的,多亏了 gsap.context 。
基本上,您只需创建一个参考,该参考将充当父母,包含要动画的元素。
函数gsap.context有两个参数。
-
回调,您基本上将执行动画(请记住,您只会选择后代元素)。
-
将充当容器的元素。
但是现在让我们逐步进行:
1-我们定义了此组件
const App = () => {
return (
<div>
<div className="square">Hello World</div>
</div>
)
}
export default App
2-我们创建一个对包含所有其他元素的父元素的新引用。
import { useRef } from "react";
const App = () => {
const app = useRef<HTMLDivElement>(null);
return (
<div ref={app}>
<div className="square">Hello World</div>
</div>
)
}
export default App
3-创建效果。
import { gsap } from "gsap";
import { useEffect, useRef } from "react";
const App = () => {
const app = useRef<HTMLDivElement>(null);
useEffect(() => {
}, [])
return (
<div ref={app}>
<div className="square">Hello World</div>
</div>
)
}
export default App
4-在效果内部,我们创建了一个新变量,我们将分配GSAP的上下文函数。这是因为最后我们需要清理动画,并且它们不会继续执行,因此,我们将创建变量 ctx 我们将在以后使用。
import { gsap } from "gsap";
import { useEffect, useRef } from "react";
const App = () => {
const app = useRef<HTMLDivElement>(null);
useEffect(() => {
let ctx = gsap.context()
}, [])
return (
<div ref={app}>
<div className="square">Hello World</div>
</div>
)
}
export default App
5- 上下文函数接收两个参数,回调(我们将在其中设置其他动画),元素(此元素必须包含后代元素)。
请注意,第二个参数我们正在传递所有参考,我们不通过app.current 。
。
立即执行使用效果清理功能。我们使用以前声明的变量CTX,并执行方法 reverver()清理动画,以使它们未执行。
import { gsap } from "gsap";
import { useEffect, useRef } from "react";
const App = () => {
const app = useRef<HTMLDivElement>(null);
useEffect(() => {
let ctx = gsap.context(() => {}, app);
return () => ctx.revert();
}, [])
return (
<div ref={app}>
<div className="square">Hello World</div>
</div>
)
}
export default App
6-现在我们可以执行上下文方法中定义的回调中的动画。
让我们作为I showed you before
制作动画如果您注意到上下文回调中的动画,这与我之前提到的最佳实践有些矛盾,因为我们将元素恢复到其课程中。 ðÖ
,但优势是您不必为要动画的每个元素创建参考ð
import { gsap } from "gsap";
import { useEffect, useRef } from "react";
const App = () => {
const app = useRef<HTMLDivElement>(null);
useEffect(() => {
let ctx = gsap.context(() => {
gsap.to(".square", { rotate: 360, duration: 5 });
//gsap.to(".square2", { rotate: 360, duration: 5 });
//gsap.to(".square3", { rotate: 360, duration: 5 });
}, app);
return () => ctx.revert();
}, [])
return (
<div ref={app}>
<div className="square">Hello World</div>
</div>
)
}
export default App
请注意,如果您想为不是引用的父元素的后代动画元素( .square2 ),您将无法在上下文中对其进行动画作用,除非您将元素移至引用元素中,以使其成为子元素。
带有.square2类的元素不会动画,因为它不是具有 ref ref 的元素的子元素。
useEffect(() => {
let ctx = gsap.context(() => {
gsap.to(".square", { rotate: 360, duration: 5 });
gsap.to(".square2", { rotate: 360, duration: 5 }); // Don't work ❌
}, app);
return () => ctx.revert();
}, [])
<div ref={app}>
<div className="square">Hello World</div>
</div>
<div className="square2">Hello World</div>
使用时间表。
时间表将帮助我们按顺序创建动画。
,要创建一个时间表,我们将以以下方式进行。
我们实际上拥有所有以前的代码,其中我们使用GSAP的上下文函数。
只是目前的回调是空的,我们在类 square2 和“ Hello World 2”中添加了一个新的DIV元素。
import { gsap } from "gsap";
import { useEffect, useRef } from "react";
const App = () => {
const app = useRef<HTMLDivElement>(null);
useEffect(() => {
let ctx = gsap.context(() => {}, app);
return () => ctx.revert();
}, [])
return (
<div ref={app}>
<div className="square">Hello World</div>
<div className="square2">Hello World 2</div>
</div>
)
}
export default App
要创建时间表,我们将使用新的参考。
const tl = useRef<GSAPTimeline>()
现在在上下文的回调中,参考 tl 我们将分配GSAP的功能时间表。
这将帮助我们避免每次渲染组件时创建新的时间表。
let ctx = gsap.context(() => {
tl.current = gsap.timeline()
}, app);
so,要在元素中添加动画,我们只需执行具有所需参数的动画类型。
如下:
let ctx = gsap.context(() => {
tl.current = gsap.timeline().to(".square", { rotate: 360 }).to(".square2", { x: 200});
}, app);
对于更好的代码读取,我们可以将代码放置:
let ctx = gsap.context(() => {
tl.current = gsap.timeline()
.to(".square", { rotate: 360 })
.to(".square2", { x: 200 })
}, app);
这意味着首先使用类 .square 将动画执行到元素,直到该动画完成后,将执行下一个动画,该动画将用于class .square2 。
当然,可以配置动画的持续时间,以便同时执行它们或类似的内容。
代码看起来像这样:
import { gsap } from "gsap";
import { useEffect, useRef } from "react";
const App = () => {
const app = useRef<HTMLDivElement>(null);
const tl = useRef<GSAPTimeline>()
useEffect(() => {
let ctx = gsap.context(() => {
tl.current = gsap.timeline()
.to(".square", { rotate: 360 })
.to(".square2", { x: 200 });
}, app);
return () => ctx.revert()
}, [])
return (
<div ref={app}>
<div className="square">Hello World</div>
<div className="square2">Hello World 2</div>
</div>
)
}
export default App
通过互动来动画。
您还可以通过与元素进行的交互执行动画,不仅在启动应用程序和使用效率时。
例如,通过事件单击一个元素,您可以触发一些动画。
请注意,该功能HandleClick接收了事件。为此,我们可以访问我们提供的单击元素。
和那个元素( e.target )是我们将动画传递给' gsap 。
的“ ”
import { gsap } from "gsap";
const App = () => {
const handleClick = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
gsap.to(e.target, { rotation: '50', yoyo: true, repeat: 1 })
}
return (
<>
<div onClick={handleClick} >Hello World</div>
</>
)
}
export default App
您不仅可以通过单击事件进行此操作,还可以通过其他几个事件(例如OnMouseenter或Onmouseleave)进行此操作。
import { gsap } from "gsap";
const App = () => {
const handleClick = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
gsap.to(e.target, { rotation: '50', yoyo: true, repeat: 1 })
}
const onEnter = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
gsap.to(e.target, { scale: 1.2 });
};
const onLeave = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
gsap.to(e.target, { scale: 1 });
};
return (
<>
<div
onMouseEnter={onEnter}
onMouseLeave={onLeave}
onClick={handleClick}
>Hello World</div>
</>
)
}
export default App
•避免尚未定型的内容闪光。
当然,您已经注意到,当您启动该应用程序并且必须在开始时执行动画时,您会注意到要动画的内容,但没有CSS样式,此后已经执行了相应的动画。
沿此路径,您已经看到我们使用使用效率在应用程序启动时执行动画。但是使用在DOM被绘制后执行,这就是为什么发生这种不必要的闪光灯的原因。
为了避免这种闪光灯,我们将使用 uselayouteffect ,它与使用效果完全相同,但区别在于,在DOM涂漆 >。
这是从GSAP文档中获取的一个示例,正是我们要避免的。
我们通过使用 uselayouteffect
避免这种情况
import { gsap } from "gsap";
import { useLayoutEffect, useRef } from "react";
const App = () => {
const app = useRef<HTMLDivElement>(null);
useLayoutEffect(() => {
let ctx = gsap.context(() => {
gsap.to(".square", { rotate: 360, duration: 5 });
}, app);
return () => ctx.revert();
}, [])
return (
<div ref={app}>
<div className="square">Hello World</div>
</div>
)
}
export default App
结论。
GSAP库肯定非常有趣,因此我希望我能帮助您了解如何使用React JS使用良好的实践和技巧。 ð
顺便说一句,另一个提示是不要使所有内容动画。另外,您只能为转换或不透明度等动画属性,并避免在浏览器中消耗大量CPU 。
确保动画在低端设备上工作。
如果您知道使用此图书馆或另一个库制作动画的其他不同或更好的方法,请随时评论。
我邀请您检查我的投资组合,以防您有兴趣与我联系以进行一个项目! Franklin Martinez Lucas
ðµ不要忘记在Twitter上也关注我:@Frankomtz361
富兰克林·马丁内斯@Frankomtz361你好呀! ð
我叫富兰克林·马丁内斯(Franklin Martinez)。
我是前端开发人员,我专注于JavaScript和React JS Technologies。
我也喜欢发表一些文章。
这是我的投资组合,看看。 ðfranklin-dev.netlify.app03:42 AM -29 Sep 2022