今天我学习了如何在 CSS(和 JavaScript)中为文本渐变制作动画🤔...🤔...🤔...总结一下:

2025-06-07

今天我学习了如何在 CSS(和 JavaScript)中制作文本渐变动画

🤔 ...🤔 ...🤔 ...

综上所述:

封面照片由 Clem Onojeghuo 拍摄,来自 Unsplash。

非常抱歉。不客气。

看看那糟糕的“咕噜咕噜”声。我感觉我的CPU都烧着了……可怜的家伙真是拼尽全力。我终于明白为什么CSS大佬们不让我这么做了。

第一部分:获取文本渐变

您可能会注意到代码的这一部分:



@mixin lead($one, $two, $three, $four, $five, $six) {
  background: linear-gradient(80deg, $one, $two, $three, $four, $five, $six);
  background-clip: text;
  text-fill-color: transparent;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}


Enter fullscreen mode Exit fullscreen mode

这就是这场灾难中实际产生“彩虹文本”部分的原因。

background部分只是生成渐变本身;你可能以前在其他地方见过那种经典的彩虹效果。去掉那个 mixin 里的所有 和background-cliptext-fill它看起来就像这样:

文本

所有其他的东西都使文本看起来像背景。

通常,background-clip 属性用于微调边框和填充等周围的背景外观,但“text”值非常神奇。

文本填充颜色大致相当于你的标准color属性。(对于这支笔,你也可以轻松地替换它color: transparent,我试过了,确实有效。)在这种情况下,我们可以将其设置为“透明”,这样我们的背景就会透过来。

那么,获取“彩虹文本”的步骤如下:

  • 背景变成了彩虹
  • 背景被剪裁,因此唯一显示的部分是通常被文本覆盖的部分
  • 文本是透明的,所以我们可以透过它看到背景

第二部分:你可以为背景添加动画,但不能使其成为线性渐变

一切从这里开始变得脱轨。我最初的方法是直接把一个渐变贴transition在一个容器上,然后就完事了;这大概需要五分钟,而且大部分时间都用来在谷歌上搜索如何让渐变与背景贴合。

然而

是时候尝试另一种策略了。



<div id="main" class="container lead-red">
  HAPPY PRIDE MONTH
</div>
<div id="fade" class="container lead-orange">
  HAPPY PRIDE MONTH
</div>


Enter fullscreen mode Exit fullscreen mode

等等,为什么有两个-

🤔



function intervalFunction() {
  rainbowify();
  setTimeout(intervalFunction, getNextTimeoutDuration());
};

intervalFunction();


Enter fullscreen mode Exit fullscreen mode

你在间歇期做什么?

🤔 ...🤔 ...🤔 ...

哦不。

要点如下:

让两个几乎相同的 HTML 元素相互重叠。第一个元素#main位于底层,始终可见;它在渐变之间以恒定的不透明度“闪烁”。第二个元素#fade位于顶层,始终闪烁(对齐时)和淡出(使用 实现过渡效果opacity)。

这两个元素并不在同一个“彩虹周期”上——#fade文本的颜色比 的颜色要早一种#main。JavaScript 使用 setInterval 循环来调整这两个元素的类,以保持颜色的动态变化。

那也没有用。

第三部分:闪烁,淡出

我的代码大致如下:在主 setInterval 循环中,尝试使用一个.halt将 transition-timing 属性设置为 0ms 的类来暂停动画(实际上禁用了过渡效果)。然后,我将不透明度设置为 1,使其“闪烁”,并移除该类.halt。之后,我将不透明度重新设置为 0,让过渡效果发挥它的魔力。这一切立即完成,只用了大约四行代码。

其实,CSS 过渡并非如此。事实上,为了实现过渡,渲染引擎需要几毫秒的时间来完成所有操作,无论当时元素上的 transition 属性是什么。

事实证明,几乎立即添加然后删除一个类是不够的。

我尝试过一段时间的过渡时间和其他 CSS,最后放弃了,转而尝试 JavaScript。最初的 JS 技巧是setTimeout( ... , 20)在现有的 setInterval 循环中使用一个,大约 95% 的情况下都有效。如果设置较低的超时时间,过渡效果会因为跟不上而出现卡顿;如果设置较高的超时时间,动画中会出现非常明显的停顿。然而,我并不想让这些奇怪的魔法数字和 Blinky McBlinkerton 的偶尔造访搞砸……

第四部分:减少抖动

我首先想消除的是那个神奇的 20ms 超时。我在 Google 上搜索了很久,终于找到了这个:

在删除和添加类名之间触发重排。

这解释了这一点:



fade.classList.add("halt");
fade.classList.add("hide");
fade.classList.remove("lead-" + rainbow[(i + 1) % ilen]);
fade.classList.add("lead-" + rainbow[(i + 2) % ilen]);

void fade.offsetWidth; // <- this one!

fade.classList.remove("halt");
fade.classList.remove("hide");



Enter fullscreen mode Exit fullscreen mode

我觉得接下来要提前考虑的怪事是JS 计时器漂移。我以前在构建时间表和时钟时就遇到过这种情况;指定的 ​​1 毫秒在现实中并不总是1 毫秒,因此任何间隔都不可避免地会越来越偏离准确度。由于我的 SCSS 和 JS 代码中硬编码了相同的超时时间,如果它们能够保持一致,效果肯定会更好。这可以防止因计时器漂移而导致的进一步停顿、卡顿等问题。

为此,我使用 setTimeout 而不是 setInterval,并让超时函数调用另一个函数,该函数再调用另一个超时函数(实际上是在超时函数之外创建一个间隔)。每次超时都会记录其开始时间,并记录与上次超时之间的“偏差”,然后进行自我修正,以更准确地达到长期目标。如果我要转向类似这样的方法,这绝对会很有用@keyframes

综上所述:

托马斯小火车斜眼凝视远方,标题为

这太复杂了,而且运行起来像冬天的糖蜜一样慢。做个动图什么的就好了。

(预计到达时间:请在此处跟进。如果出于某种原因您确实这样做...)

但我做到了,CSS 霸主们。我打败了你们。我胜利了。

文章来源:https://dev.to/tchaflich/today-i-learned-how-to-animate-a-text-gradient-in-css-and-javascript-2ehp
PREV
从创意到发布:开发者指南:创建你的第一个创业公司 📚 目录:从创意到发布 – 开发者指南:创建你的第一个创业公司
NEXT
使用 CSS / Tailwind 的下拉菜单