React中的动画火花

303 阅读12分钟

简介

在网络上,当我们想表示一句话的某个部分特别重要时,我们可以使用两个语义标签:<strong><em>

  • 根据MDN<strong> 元素是用来表示 "非常严肃或紧急 "的事情,如警告。

  • <em> 元素是为了表示语言压力,以便你的内部叙述者能够准确地再现信息并推断出正确的含义。比如说。"为什么杰里会带来什么?","为什么杰里会带来什么?"*。

这两个元素经常一起使用,以强调可怕的警告或关键的严重情况。不要打开太空船的窗户,你会被吸进太空

但是,当我们想强调一些积极的东西时呢?在我们的非数字生活中,我们可以使用语气、时机和身体语言来表达各种情绪。我们在网络上的唯一工具与紧张和严肃的情况有关,这有点糟糕。

对于我的博客来说,我希望有更多的表现力,而不是单单这些标签所能提供的。所以我正在研究一些新的标签*。我从这个辛辣的草书变体开始,最近我又增加了第二个:闪光的文字

闪光表示某些东西是新的和闪亮的,或者某些东西已经吸引了我的感情。它的目的是增加突出性,但以积极的方式!我们可以在更多的地方使用它。

我们不仅可以在文字上使用它,也可以在其他地方使用。这里有一些例子。

彩虹文字

彩虹!

在一个图像上

An open bottle of gold glitter

闪烁按钮

开始吧!

今天我们要探讨一下这是如何建立的,这样你就可以在你的项目中也有闪光的文字了

预期受众

这篇博文是为那些熟悉React(包括自定义钩子)的人写的。有一点动画经验也是有帮助的,尽管这并不是必须的。

[

链接到这个标题

](www.joshwcomeau.com/#planning-i…

从界面的角度来看,我想象它是这样工作的。

jsx

每个火花将是它自己的HTML元素,一个span 。我们将有某种循环,一秒钟增加几个元素。每个元素将使用关键帧动画来闪烁:缩放和旋转的组合。

如果我们不小心,我们会用一堆陈旧的闪光元素污染DOM,所以我们也需要清理自己;我们将定期进行垃圾收集,并删除已经完成闪烁的节点。

最后,我们将在子元素形成的盒子里随机地定位每个火花。

每个火花都应该有一定的独特性,以保持事情的趣味性。

有了这个游戏计划,让我们开始制作吧首先,我们需要一个火花资产。

[

链接到这个标题

](www.joshwcomeau.com/#creating-a…

在本教程中,我们将使用以下资产。

A sparkle image, essentially a curvy 4-pointed star

它是一个SVG,不是JPG或PNG。我们希望它是一个SVG,这样我们就可以动态地改变它:通过使用内联SVG元素,我们可以用JS改变fill 的颜色

有很多方法可以得到一个合适的SVG。

  • 在Noun项目中搜索一个。

  • 下载我创建的那个(右键单击并 "另存为...")。它是在知识共享零条款下发布的。

  • 制作你自己的!

我使用Figma来满足我所有的插图需求。这是一个令人难以置信的免费软件。它是跨平台的,有桌面和网络应用两种类型(它甚至用React构建!)。

我录制了一个1分钟的教程,介绍如何使用Figma来创建一个闪亮的SVG。

作为一个开发者学习 Figma

我不是一个设计师,我想说我的 Figma 技能介于 "初级 "和 "中级 "之间。我绝对不能像专业设计师那样熟练地使用它。

不过,即使是最基本的技能,有时也觉得它是一种超能力。能够快速想出我自己的资产,在我的副业项目上帮助了我很多次。更不用说它的原型设计有多快了。我强烈建议你花些时间来熟悉它,或其他设计工具。

[

链接到这个标题

](www.joshwcomeau.com/#generating…

我们需要一个函数来创建一个新的 "sparkle "实例。

每个火花都应该有一个ID,一个随机的大小,和一个随机的位置。这里有一个第一遍。

js

random 函数是一个在一定范围内生成随机数的工具。查看完整的片段

只要我们需要一个新的火花,我们就可以调用这个函数,它将有一个随机的位置。我们使用百分比进行布局,因为我们实际上不知道我们容器的宽度和高度。

我们将创建一个新的SparkleInstance 组件,它将消耗其中的一些数据来渲染一个火花。

早些时候,我们在Figma中创建了一个插图。

A curvy 4-pointed star illustration

我们可以将其导出为SVG,最后得到的东西看起来像这样。

svg

SVG的好处是,它们几乎已经是JSX了!我们可以使用一个漂亮的工具,将SVG导出。我们可以使用像svg2jsx这样的漂亮工具来调整那些需要改变的小细节。我们将使用这个SVG作为一个新的React组件的基础,SparkleInstance

jsx

每个sparkle实例都会有自己的颜色、大小和位置,所以这些都是我们新组件的道具。以前在我们的SVG中固定的值在道具的驱动下变成了动态的。

我把svg ,用一个有风格的组件,Svg 。这让我们可以为我们的闪光点添加一些基本的样式。

这些例子使用了styled-components,但本教程并不针对任何风格化的解决方案。这对直接使用CSS、PostCSS、Sass也是一样有效的...。

让我们创建一个React组件,并开始渲染一个单一的火花。我们将把它放在我们传递给它的任何children

jsx

回顾一下。

  • 我们已经创建了一个随机大小和位置的单一SparkleInstance

  • 我们给了它一个2的Z-index。

  • 我们的children 被包裹在一个ChildWrapper 中,而这个strong 是一个z-index为1的标签。

  • 这两个元素都被包裹在一个Wrapper

这样一来,我们就有一个闪光点被胡乱地生成在我们包裹的元素上面了点击/敲击按钮来生成一个随机的新火花。

重新生成

请注意,即使你在火花所在的地方点击/轻拍,你仍然可以触发这个按钮。这是因为我们添加了pointer-events: none ;我们的点击/敲击可以直接通过它。

在我们有一个工作的原型之前,我们还有两个步骤。

  1. 添加动画,使每个火花看起来都是闪烁的。

  2. 定期生成和清理火花。

[

链接到这个标题

](www.joshwcomeau.com/#twinkling-…

我们希望我们的火花能以两种方式变化。

  • 它应该旋转,相对缓慢

  • 它应该增长和缩小

transform 属性可以帮助我们实现这两个目标。作为第一次尝试,我们可以做这样的事情。

jsx

这使用了来自styled-components的keyframes 帮助器。它的功能与 "普通的 "CSS关键帧动画非常相似。在styled-components文档中了解更多

我们的动画从scale(0) 开始,这意味着它被缩小到不可见的程度(正常尺寸的0倍)。在50%的时候,我们已经长到了它的全尺寸(1倍),并将它旋转了90度。当动画完成时,我们又旋转了90度,并缩回到0x大小。

"向前"?

当我们将关键帧动画应用于Svg ,我们在末尾添加了 "forwards "一词。这是对animation-fill-mode属性的缩写。

让我们看看这个动画是什么样子的。点击触发器,产生一个火花(我把它放大了,这样我们就可以清楚地看到效果)。

点击我

🤔这不是超级闪烁的,是吗?我看到两个问题。

  1. 每一步都是缓和的,所以你会得到一个生硬的两步动画;它在中间有点停顿,因为它正在缓和到50%的关键帧。

  2. 有两个属性正在被调整--旋转和缩放--而且它们是完全同步发生的。我想把这些属性分开处理,这样它们的时间和缓和就可以独立控制。

为了使本教程相对简短,我略过了很多动画原理。如果你对学习基础知识感兴趣,我也会写这些内容的订阅我的新闻通讯,可以提前获得新的教程和文章。

我们需要做的第一件事是把动画分离出来。我希望能够分别控制缩放和旋转。为了做到这一点,我需要一个包裹性的div:你可以在一个元素上放置多个关键帧动画,但如果它们都修改相同的属性就不行。在我们的例子中,两个关键帧都是在调整transform 属性。

我们不在SVG上设置一个关键帧,而是在一个父元素上添加第二个关键帧。我们将调整易位,使我们的旋转是线性的,而我们的缩放父元素有一个对称的易位。

jsx

有了这个分割,事情看起来就顺畅多了。

点击我

[

链接到这个标题

](www.joshwcomeau.com/#generation…

最后一项任务就在我们的路上。动态生成一堆火花,并在它们完成闪烁后对其进行清理。

我的第一直觉是去找setInterval 。这个方法让你在一个异步循环中安排更新。例如,我们可以每隔500ms添加一个新的火花。

这种方法的问题是,它给人一种超级机器人/合成的感觉。我想要的是感觉更加有机和杂乱无章的东西。我不希望新火花的节奏如此错落有致。

我创造了一个新的钩子,useRandomInterval 。它的工作原理与setInterval ,只是你传递给它两个数字,一个最小值和一个最大值。对于每一次迭代,它都会在这个范围内挑选一个随机数字。这导致了一个更自然的效果。下面是一个并列的比较,每个人平均每秒产生2个火花。

恒定间隔

火花文本

随机区间

闪光文本

自定义钩子的好处是,它们可以完全抽象出很多复杂的东西。我已经把这个useRandomInterval 钩子作为一个片段发布了。如果你感到好奇,你可以阅读它是如何工作的,但不要觉得有什么义务;你可以自由地复制/粘贴它,并像使用setInterval

在我们的区间内,我们将做两件事。

  1. 产生一个新的火花。

  2. 清理任何旧的火花。

下面是它的样子。

jsx

[

链接到这个标题

](www.joshwcomeau.com/#accessibil…

像闪光文本这样的异想天开的功能很好,但重要的是它们不会以牺牲可访问性为代价。

在《React中的无障碍动画》中,我们研究了 "prefers reduced motion "媒体查询如何让人们表明他们不希望看到任何动画。usePrefersReducedMotion钩子让我们可以从JS中访问这个值。

在这种情况下,我想做两件事。

  1. 禁用 "闪烁 "动画。

  2. 禁用添加它们并清理它们的随机间隔。

如果这个人喜欢减少动作,我们可以生成3-4个火花,并以静态方式呈现。

The text 'This is what people will see when they prefer reduced motion'. The last 3 words are bold, and there are 4 sparkles decorating them. They're static, and don't move at all.

我们将用这组火花初始化我们的sparkles 状态,如果运动被禁用,则禁用我们的useRandomInterval 循环。

jsx

range 是一个我用来生成数组的实用函数。我在这里用它来创建一个充满4个随机火花的数组。了解更多

我们可以通过传递null 作为最小/最大时间来完全禁用该循环。令人高兴的是,这个钩子是完全响应的,这意味着用户可以切换他们的 "喜欢减少运动 "状态,而我们的火花将根据需要冻结。

最后一步--我们需要在CSS中,当媒体查询被匹配时,禁用两种动画。

jsx

[

链接到这个标题

](www.joshwcomeau.com/#pulling-it…

这是我们建立的代码的最终版本。

jsx

为了使其发挥作用,你需要一些依赖性。

[

链接到这个标题

](www.joshwcomeau.com/#just-the-b…

这个<Sparkles> 组件有点像MVP;它完成了工作,但还有很大的改进空间。

在这个博客上,我擅自做了一些其他的改动。

  • 火花可以出现在孩子的前面或后面

  • 火花的位置不完全是随机的,我试着挑选漂亮的安排

  • 你可以点击闪闪发光的文字来关闭这个效果

上面的代码片段是为了作为你自己调整和定制的起点。这个效果之所以令人愉快,很大一部分原因是它是独一无二的。要有创造性,并在其中加入你自己的调整!

我们没有制作一个不透明的NPM包,而是从头开始构建这个效果。现在轮到你在它的基础上,添加你自己独特的触摸。

我迫不及待地想看看你能想出什么办法来!

最后更新

2020年5月19日

点击率