使用纯 CSS 实现渐变动画
在本文中,我将演示如何仅使用 HTML 和 CSS 实现无限线性渐变动画。这并非唯一的渐变动画技术,但我发现它是最优雅、最通用的方法之一。
第一部分:理解技术
这种动画技术运用多种元素来实现这种效果。
首先,让我们在场景中确定这些元素及其相关词汇:
- 舞台——一个父容器,用于指定动画可见区域的起始和结束位置。可以把它想象成一个剧院舞台,左右两侧被幕布遮挡。从舞台可见区域延伸到幕布后面的所有内容,观众都将无法看到。目前,为了演示目的,所有内容都处于可见状态。
- 传送带——舞台内嵌套的子容器,用于容纳视觉上可区分的元素。可以把它想象成超市传送带的一部分。传送带上的物品是静止的,但传送带本身会带动物品在空间中移动。动画就是由传送带实现的。
- 元素——腰带内一系列视觉上可区分的元素。本例中使用的是点。稍后,我们将使用渐变。无论选择哪种元素,都需遵守以下几条规则:
方面规则
- 序列中必须至少包含两个方面。
- 第一个方面和最后一个方面必须相同。
- 各个部件必须沿传送带均匀分布。
- 注意:这里使用 Flexbox 实现了均匀间距
justify-content: space-around。
- 注意:这里使用 Flexbox 实现了均匀间距
在这个例子中,我们的目标是让舞台上的元素从左到右依次呈现动画效果,因此首先将传送带的位置向舞台左侧偏移。传送带的宽度和偏移距离至关重要,它们决定了动画过程中任何时刻可见区域内会出现多少个元素。
此动画包含两个部分,每次只会显示其中一个部分。这意味着,在动画的单次迭代结束时,序列的最后一个部分(部分 2)必须在屏幕上与序列的第一个部分(部分 1)出现的位置完全相同。
基本思路
从舞台最右侧边缘的腰带右侧开始,移动腰带,直到其左侧到达舞台最左侧边缘。
当传送带完成一次动画迭代后,它会立即传送回原来的位置,序列的最后一个部分(第 2 部分)会在视觉上取代序列的第一个部分(第 1 部分),并继续进行下一次动画迭代。
这就是它的样子:
然后,只需overflow: hidden在舞台上应用一个遮罩,它的两侧就会像剧院幕布一样正常运作,从而在可见区域内营造出永动的错觉:
如您所见,在任何给定时间,两个方面中只有一个方面是完全可见的。
奖励示例
以下是同一设置下三个方面的样子:
应用之后overflow: hidden,三个方面中的两个在任何给定时间都能完全可见。
请注意,动画开始时的第二和第三个方面与动画结束时的第一个和第二方面看起来完全相同。
第二部分:渐变动画
我们先来建立第一个基本的HTML元素:舞台。article这里我们使用了一个<div>标签,但任何HTML元素都可以替换。
<article class="stage"></article>
在 CSS 中为其指定任意尺寸,以定义可见区域:
.stage {
height: 200px;
width: 200px;
}
添加一些可选的演示样式:
body {
background-color: #8fb6ff;
margin: 0;
padding: 3rem;
}
.stage {
background-color: #fff;
box-shadow: 0 3px 14px #000;
border-radius: 1rem;
height: 200px;
width: 200px;
}
由于我们使用渐变作为元素,我们可以利用 CSS3 的特性,background-image: linear-gradient()让舞台背景同时充当腰带和元素,从而避免编写多余的 HTML 代码。舞台的 `<head>` 标签background-image将创建腰带,而 `<body>` 标签linear-gradient()将定义元素。
添加渐变色
background-image: linear-gradient(90deg, #da3287, #ffde5e);
方便之处在于,浏览器技术已经发展到如此先进的程度,以至于不再需要linear-gradient为该 CSS 函数添加浏览器厂商前缀,它就可以在所有现代浏览器中正常工作。
在这种动画技术中,渐变是一种表现形式。将渐变中的每一对颜色视为一个单独的元素,就更容易将渐变抽象为表现形式。
目前只有一个方面,即从樱桃红到芥末黄的渐变,这违反了方面的规则,因为一个序列中至少需要两个方面。
让我们复制这组颜色,创建另外两个方面。
background-image: linear-gradient(90deg, #da3287, #ffde5e, #da3287, #ffde5e);
现在有三个方面:
- 从樱桃红到芥末黄的渐变
#da3287, #ffde5e - 从芥末黄到樱桃红的渐变
#ffde5e, #da3287 - 从樱桃红到芥末黄的渐变
#da3287, #ffde5e
设置腰带宽度
目前所有元素都显示在舞台上。需要进行更改,以确保在动画播放过程中每次只显示一个元素。
此动画将沿 X 轴方向进行动画,这意味着需要调整舞台传送带的宽度background-size。这可以通过将 X 轴的宽度(100%) 乘以纵横比 (3) 来实现。
background-size: 300% 100%;
Y 轴设置为 100%,因为我们希望渐变覆盖舞台的整个高度。
虽然看起来和以前一样,但舞台背景(腰带)实际上在水平方向上已经超出其父容器边界三倍。这一点不明显,因为舞台本身起到了限制可视区域的作用。
腰带和各个部件都准备就绪,剩下的就是动画制作了。
腰带动画
background-position舞台(即舞台边缘)的顶部位置background-image由浏览器0 0默认设置。这意味着渐变效果位于舞台的左上角。
我们希望背景的位置从其最左侧边缘(当前位置)动画移动到其最右侧边缘。
这些@keyframes描述了动画行为:
@keyframes animateBg {
0% {
background-position: 0 0;
}
100% {
background-position: 100% 0;
}
}
最后,将这种行为赋予舞台。
.stage {
animation: animateBg 2s infinite linear;
...
瞧,一个向左无限移动的线性动画渐变就完成了。
工具
CSS渐变动画器
这是Ian Forrest的经典工具,它采用略有不同的技术来实现缓动、振荡的动画效果。
纯 CSS 动画渐变生成器
我最近用 React 写了一个工具,可以生成我们刚才用来创建无限线性动画渐变的 CSS。它允许你自定义颜色、持续时间和方向。
我也已将此工具开源到 GitHub 和 GitLab 上,欢迎任何想要贡献功能或改进的人:
反复使用这些工具应该能让你更深入地了解渐变动画背后的原理。
欢迎提出批评和建议。
感谢阅读。👍
文章来源:https://dev.to/gmeben/animating-gradients-with-pure-css-3bi8