使用 React Hooks 和 GreenSock 实现动画
作者:Paul Ryan✏️
探索 Web 动画的世界,既可以是一段精彩的旅程,也可以是一段令人疲惫的旅程。我的目标是让它成为一段精彩的旅程,同时利用 React Hooks 的强大功能进一步提升你的学习体验。
我需要知道什么?
本文不应被视为 JavaScript 或 React 的入门指南。我将逐一解释我们使用到的概念,但您至少应该对两者都有一定了解。您可以点击此处查看 React 文档。
我们将要创造什么?
我喜欢以身作则。光是把一堆概念和文字塞给你,对你的学习没有任何帮助,而且说实话,这对我们俩来说都会很枯燥。我们将制作两个独立的动画,每个动画的难度都会逐渐增加。
我们的第一个动画将是一个简单的加载器,类似于谷歌的:
我们的第二个目标是将 LogRocket 徽标制作成动画,使其变得更好!
开始设置
设置快捷简单:我在这里创建了一个 CodeSandbox,它有 GreenSock npm 模块,也有 React,所以您只需分叉它并继续操作即可。
Google 风格的加载器
现在我们可以开始创建Loader
组件了。如果你能跟着我一起做就更好了,不过最后我会附上完整的 CodeSandbox 链接。
我们的加载器首先需要的是图形,我已经创建好了。SVG 是一个基础的 SVG,只包含一些标记。
<svg viewBox="0 0 150 33.2" width="180" height="150">
<circle ref={circle} cx="16.1" cy="16.6" r="16.1" fill="#527abd" />
<circle ref={circle} cx="55.2" cy="16.6" r="16.1" fill="#de4431" />
<circle ref={circle} cx="94.3" cy="16.6" r="16.1" fill="#f4b61a" />
<circle ref={circle} cx="133.4" cy="16.6" r="16.1" fill="#009e52" />
</svg>
然后,在我们的源代码中,我们可以创建一个Loader
组件,这就是奇迹发生的地方。
在组件内部Loader
,我们想要渲染我们的图形。
// src/loader.jsx
import React from "react";
const Loader = () => {
return (
<svg viewBox="0 0 150 33.2" width="180" height="150">
<circle cx="16.1" cy="16.6" r="16.1" fill="#527abd" />
<circle cx="55.2" cy="16.6" r="16.1" fill="#de4431" />
<circle cx="94.3" cy="16.6" r="16.1" fill="#f4b61a" />
<circle cx="133.4" cy="16.6" r="16.1" fill="#009e52" />
</svg>
);
};
export default Loader;
您现在应该看到:
太棒了!现在图形已经制作好了,接下来我们来制作动画吧。
动画制作时,首先需要的是要制作动画的元素的引用。为了获取元素的引用,我们可以使用useRef
Hook。useRef
它会返回一个 ref 对象,该对象包含一个current
属性,而这正是动画的目标。
创建useRef
很简单:
const myElement = useRef(null)
因此,对于我们的情况,我们需要定位四个元素。我们将创建四个引用,如下所示:
const blue = useRef(null);
const red = useRef(null);
const yellow = useRef(null);
const green = useRef(null);
然后我们可以将这些引用添加到我们的 SVG 中:
<svg viewBox="0 0 150 33.2" width="180" height="150">
<circle ref={blue} cx="16.1" cy="16.6" r="16.1" fill="#527abd" />
<circle ref={red} cx="55.2" cy="16.6" r="16.1" fill="#de4431" />
<circle ref={yellow} cx="94.3" cy="16.6" r="16.1" fill="#f4b61a" />
<circle ref={green} cx="133.4" cy="16.6" r="16.1" fill="#009e52" />
</svg>
我们的组件现在看起来像这样:
// src/loader.jsx
import React, { useRef } from "react";
const Loader = () => {
const blue = useRef(null);
const red = useRef(null);
const yellow = useRef(null);
const green = useRef(null);
return (
<svg viewBox="0 0 150 33.2" width="180" height="150">
<circle ref={blue} cx="16.1" cy="16.6" r="16.1" fill="#527abd" />
<circle ref={red} cx="55.2" cy="16.6" r="16.1" fill="#de4431" />
<circle ref={yellow} cx="94.3" cy="16.6" r="16.1" fill="#f4b61a" />
<circle ref={green} cx="133.4" cy="16.6" r="16.1" fill="#009e52" />
</svg>
);
};
export default Loader;
一切就绪后,我们就可以开始使用 GreenSock 了。
首先我们导入TweenMax
。
import { TweenMax } from "gsap";
TweenMax 是 GreenSock 的一个功能齐全的模块,可以帮助我们创建动画。它有很多方法,我们将使用其中几个!
GreenSock 还为我们提供了 TweenLite,这是一个功能较少但更轻量级的模块。
对于动画,我们希望它在组件挂载时发生。在传统的基于类的组件中,我们会使用componentDidMount
,但对于 Hooks,我们将使用useEffect
,它的行为与 Hooks 相同,但有一些细微的差别。想要深入了解 Hooks,你应该看看 Dan Abramov 的这篇精彩文章。
因此,当我们的组件挂载时,我们将使用 TweenMax 的fromTo
方法来为圆圈添加动画。该fromTo
方法传递了四个参数:
fromTo(element(s), duration, start, end)
让我们集中精力让blue
圆圈上下移动。为此,我们将瞄准y
动画的属性。
因此我们的代码如下:
TweenMax.fromTo(blue.current, 5, { y: 18 }, { y: -18 });
我们首先定位元素,然后设置持续时间5s
。我们从y
位置开始18
,到 结束-18
。如下所示:
好的,我们取得了一些进展,但仍然存在一些问题——速度太慢,而且我们还需要动画无限循环。让我们解决这些问题。为此,我们需要做的就是在对象中添加yoyo
和repeat
属性to
。
TweenMax.fromTo(blue.current, 0.5, { y: 18 }, { y: -18, yoyo: true, repeat: -1 });
yoyo
表示动画将yoyo
在起始位置和结束位置之间移动。设置repeat
为-1
将使动画无限循环。我们还将持续时间设置为半秒,这样速度会更快。
现在,随着我们新房产的到位,我们拥有:
从上面完成的动画中可以看到,黄色圆圈的行为与蓝色圆圈相同。考虑到这一点,我们可以将一个元素数组(ourblue
和yellow
ref)传递给我们的fromTo
方法。
TweenMax.fromTo(
[blue.current, yellow.current],
0.5,
{ y: 18 },
{ y: -18, yoyo: true, repeat: -1 }
);
所以现在我们有:
成功了!我想你现在应该能感受到 GreenSock 的强大了。为了完成动画,我们只需要将红球和绿球以相反的方式动画起来,如下所示:
TweenMax.fromTo(
[red.current, green.current],
0.5,
{ y: -18 },
{ y: 18, repeat: -1, yoyo: true }
);
这段代码几乎和上面的代码完全相同,只是这次我们从 开始y:-18
,从 结束y:18
。
我们的最终动画现已完成,它看起来应该是这样的:
完整代码如下。
LogRocket 徽标动画
一个动画结束,还有一个!
我为 LogRocket 图标创建了一个SVG
,它很大,所以我将它包含在启动器 CodeSandbox 中,您可以在这里查看。
最终的动画将如下所示:
正如您从上面看到的,这不仅仅是我们的第一个动画,所以让我们开始吧!
我们首先要关注的是火箭,它从底部开始动画。我们有一个g
带有 的元素id
。rocket
这就是我们要用 GreenSock 实现的目标元素。以前,我们会这样做TweenMax
,但现在我们将使用 ,TimelineMax
因为我们希望每个元素按顺序动画,而不是一次性全部动画。
我们TimelineMax
像这样导入:
import { TimelineMax } from "gsap";
我们首先需要创建一个Timeline
,我们通过创建该类的实例来实现TimelineMax
:
const tl = new TimelineMax();
与 类似TweenMax
,我们的实例 ( tl
) 也有一个fromTo
我们将使用的方法:
tl.fromTo("#rocket", 2, { y: 50 }, { y: 0 });
这与我们的第一个动画非常相似,只是这里ref
我们不是使用,而是传递 id — — 无论哪种方式都可以。
现在我们的火箭应该像这样从底部升起:
下一部分是draw
字母。所有字母都path
包裹在g
带有 的标签中id
letters
,这样我们就能轻松找到它们。为了获得绘图效果,我们需要使用几个attributes
,分别是stroke-dasharray
和stroke-dashoffset
。这些相当复杂,如果您想了解更多详细信息,我建议您前往。
在我们的例子中,我们使用这些属性将路径分解成小段,以便将它们重新组合在一起,从而实现绘制效果。我的经验法则是将两个属性的值设置为相同,这样一旦文本消失,就可以继续使用了。100
是我们将采用的值。
因此,在我们的styles.css
文件中,我们将在路径上设置这两个属性,如下所示:
svg #letters path {
stroke-dasharray: 100;
stroke-dashoffset: 100;
}
附带说明一下,stroke
必须存在才能使其path
工作(这包括从父级path
继承)。stroke
因此,您现在看到的是以下内容:
这和我们之前的一样,但字母没有那么粗——那是因为我们去掉了stroke
,但它仍然有一个fill
。下一步是将 设置fill-opacity
为0
。
svg #letters path {
stroke-dasharray: 100;
stroke-dashoffset: 100;
fill-opacity: 0;
}
有了这个,我们的信件就消失了,所以现在我们专注于找回它们。
我们需要做的就是将动画strokeDashoffset
返回到0
。我们将使用我们的tl
实例和to
方法。
tl.to("#letters path", 3, {
strokeDashoffset: 0
});
如你所见,我们使用letters
选择器,然后选中path
该组中的每个字母。这样,我们的字母现在就可以开始绘制了:
最后一个难题是为fill-opacity
to制作动画1
。我们再次使用tl
实例和to
方法。
tl.to("#letters path", 3, { "fill-opacity": 1 });
就这样!我们的 LogRocket 动画完成了——还不错吧?
你可以从这里看到它的威力TimelineMax
。通常,要按顺序运行动画,你必须使用延迟,但TimelineMax
我们已经处理好了。
完整的 CodeSandbox 可以在下面找到。
结论
好了,各位,就到这里。这绝对更像是对 GreenSock 的介绍,而不是 React Hooks 的介绍,但我希望你们对两者都有所了解。GreenSock 的团队为他们的库投入了大量精力,所以一定要更进一步,用它来创作精彩的动画。
编者注:觉得这篇文章有什么问题?您可以在这里找到正确版本。
插件:LogRocket,一个用于 Web 应用的 DVR
LogRocket是一款前端日志工具,可让您重放问题,就像它们发生在您自己的浏览器中一样。您无需猜测错误发生的原因,也无需要求用户提供屏幕截图和日志转储,LogRocket 允许您重放会话以快速了解问题所在。它可与任何应用程序完美兼容,无论使用哪种框架,并且提供插件来记录来自 Redux、Vuex 和 @ngrx/store 的更多上下文。
除了记录 Redux 操作和状态之外,LogRocket 还记录控制台日志、JavaScript 错误、堆栈跟踪、带有标头 + 正文的网络请求/响应、浏览器元数据以及自定义日志。它还会对 DOM 进行插桩,以记录页面上的 HTML 和 CSS,即使是最复杂的单页应用程序,也能重现像素完美的视频。
免费试用。
使用 React Hooks 和 GreenSock 的动画一文首先出现在LogRocket 博客上。
文章来源:https://dev.to/bnevilleoneill/animations-using-react-hooks-and-greensock-2o80