正规网赌平台有趣的CSS题目(13):巧妙地制作背景色渐变动画!

Twitter的”fave”动画

2015/05/12 · HTML5 ·
Twitter,
动画

本文由 伯乐在线
刘健超-J.c
翻译,胡屹
校稿。未经许可,禁止转载!
英文出处:cssanimation.rocks。欢迎加入翻译组

有趣的CSS题目(13):巧妙地制作背景色渐变动画!

2017/03/24 · CSS ·
CSS,
动画

本文作者: 伯乐在线
chokcoco
。未经作者许可,禁止转载!
欢迎加入伯乐在线 专栏作者

有的时候,嗯,应该说某些特定场合,我们可能需要下面这样的动画效果,渐变 +
animation :

正规网赌平台 1

假设我们渐变的写法如下:

div { background: linear-gradient(90deg, #ffc700 0%, #e91e1e 100%); }

1
2
3
div {
    background: linear-gradient(90deg,  #ffc700 0%, #e91e1e 100%);
}

按照常规想法,配合 animation ,我们首先会想到在 animation
的步骤中通过改变颜色实现颜色渐变动画,那么我们的 CSS 代码可能是:

div { background: linear-gradient(90deg, #ffc700 0%, #e91e1e 100%);
animation: gradientChange 2s infinite; } @keyframes gradientChange {
100% { background: linear-gradient(90deg, #e91e1e 0%, #6f27b0 100%); }
}

1
2
3
4
5
6
7
8
9
10
div {
    background: linear-gradient(90deg,  #ffc700 0%, #e91e1e 100%);
    animation: gradientChange 2s infinite;
}
 
@keyframes gradientChange  {
    100% {
        background: linear-gradient(90deg,  #e91e1e 0%, #6f27b0 100%);
    }
}

上面我们用到了三种颜色:

  • #ffc700 黄色
  • #e91e1e 红色
  • #6f27b0 紫色

最后,并没有我们预期的结果,而是这样的:

正规网赌平台 2

See the Pen 线性渐变动画 by
Chokcoco (@Chokcoco) on
CodePen.

我们预期的补间动画,变成了逐帧动画。
正规网赌平台 3

也就是说,线性渐变是不支持动画 animation
的,那单纯的由一个颜色,变化到另外一个颜色呢?像下面这样:

div { background: #ffc700; animation: gradientChange 3s infinite
alternate; } @keyframes gradientChange { 100% { background: #e91e1e; }
}

1
2
3
4
5
6
7
8
9
10
div {
    background: #ffc700;
    animation: gradientChange 3s infinite alternate;
}
 
@keyframes gradientChange  {
    100% {
        background: #e91e1e;
    }
}

发现,单纯的单色值是可以发生渐变的:

See the Pen 单色值渐变动画 by
Chokcoco (@Chokcoco) on
CodePen.

Twitter的“fave” 动画

最近 Twitter
通过引入一段新的动画重新设计了“fave”按钮(也叫“fav”)。这段动画并不依赖
CSS transition,而是由一系列图片组成的。下面展示如何用 CSS 的
animation-timing-function 属性中的 steps 时序函数(timing
function)重新制作这段动画。

So

总结一下,线性渐变(径向渐变)是不支持 animation 的,单色的 background
是支持的。

查找了下文档,在 background 附近区域截图如下:

正规网赌平台 4

哪些 CSS
属性可以动画?
,上面的截图是不完整的支持
CSS 动画的属性,完整的可以戳左边。

对于 background 相关的,文档里写的是支持 background
但是没有细说不支持 background: linear-gradient()/radial-gradient()
。猜测原因,可能是由于渐变中加入 animation 的变化对过于消耗性能。

那么是否我们想要的背景色渐变动画就无法实现了呢?下面我们就发散下思维看看有没有其他方式可以达到我们的目标。

运动产生的错觉

这段动画的效果类似于观看古老的西洋镜,该装置呈现的是一系列连续的围绕着圆筒的插画。在下面的示例中,我们不使用圆筒,而是在某个元素内部呈现一系列图片。

通过 background-position 模拟渐变动画

上面哪些 CSS 属性可以动画的截图中,列出了与 background 相关还有
background-position ,也就是 background-position
是支持动画的,通过改变 background-position 的方式,可以实现渐变动画:

div { background: linear-gradient(90deg, #ffc700 0%, #e91e1e 50%,
#6f27b0 100%); background-size: 200% 100%; background-position: 0 0;
animation: bgposition 2s infinite linear alternate; } @keyframes
bgposition { 0% { background-position: 0 0; } 100% {
background-position: 100% 0; } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
div {
    background: linear-gradient(90deg,  #ffc700 0%, #e91e1e 50%, #6f27b0 100%);
    background-size: 200% 100%;
    background-position: 0 0;
    animation: bgposition 2s infinite linear alternate;
}
 
@keyframes bgposition {
    0% {
        background-position: 0 0;
    }
    100% {
        background-position: 100% 0;
    }
}

这里我们还配合了 background-size。首先了解下:

background-position:指定图片的初始位置。这个初始位置是相对于以
background-origin 定义的背景位置图层来说的。>
background-size:设置背景图片大小。当取值为百分比时,表示指定背景图片相对背景区的百分比大小。当设置两个参数时,第一个值指定图片的宽度,第二个值指定图片的高度。

通过 background-size: 200% 100%
将图片的宽度设置为两倍背景区的宽度,再通过改变 background-position
x 轴初始位置来移动图片,由于背景图设置的大小是背景区的两倍,所以
background-position的移动是由 0 0 -> 100% 0 。最终效果如下:

See the Pen background-position
实现渐变动画
by Chokcoco
(@Chokcoco) on
CodePen.

示例

把鼠标悬停在星星上就可以看到动画效果(请到原文查看动画效果——译者注)。

在本示例中,我们将从制作一系列能组成动画的图片开始。在这里,我们使用来自
Twitter 的“fave”图标动画的部分图片集:

正规网赌平台 5

为了能让这些帧动起来,我们需要把它们放置在一排上。在这个文件中,这些帧已经排列在一排上了,这意味着我们可以通过设置背景位置(background-position)属性使背景从第一帧过渡到最后一帧。

正规网赌平台 6

通过 background-size 模拟渐变动画

既然 background-position 可以,那么另一个 background-size
当然也是不遑多让。与上面的方法类似,只是这次 background-position 辅助
background-size ,CSS 代码如下:

div { background: linear-gradient(90deg, #ffc700 0%, #e91e1e 33%,
#6f27b0 66%, #00ff88 100%); background-position: 100% 0; animation:
bgSize 5s infinite ease-in-out alternate; } @keyframes bgSize { 0% {
background-size: 300% 100%; } 100% { background-size: 100% 100%; } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
div {
    background: linear-gradient(90deg,  #ffc700 0%, #e91e1e 33%, #6f27b0 66%, #00ff88 100%);
    background-position: 100% 0;
    animation: bgSize 5s infinite ease-in-out alternate;
 
}
 
@keyframes bgSize {
    0% {
        background-size: 300% 100%;
    }
    100% {
        background-size: 100% 100%;
    }
}

效果如下:

See the Pen position-size
实现渐变动画
by Chokcoco
(@Chokcoco) on
CodePen.

通过改变 background-size 的第一个值,我将背景图的大小由 3
倍背景区大小向 1
倍背景区大小过渡,在背景图变换的过程中,就有了一种动画的效果。

而至于为什么要配合 background-position: 100% 0 。是由于如果不设置
background-position ,默认情况下的值为
0% 0%,会导致动画最左侧的颜色不变,像下面这样,不大自然:

正规网赌平台 7

Steps() 时序函数

大多数的时序函数,例如 ease(缓冲)和
cubic-bezier(三次贝塞尔),都能让元素从初始状态平滑地过渡到最终状态。steps
时序函数与此不同,它并不是平滑地过渡,而是将过渡过程分割为一定数量的步骤,并且在这些步骤之间快速地移动。

正规网赌平台 8

我们先建立如下的 HTML 代码:

XHTML

<section class=”fave”></section>

1
<section class="fave"></section>

通过 transform 模拟渐变动画

上面两种方式虽然都可以实现,但是总感觉不够自由,或者随机性不够大。

不仅如此,上述两种方式,由于使用了 background-position
background-size,并且在渐变中改变这两个属性,导致页面不断地进行大量的重绘(repaint),对页面性能消耗非常严重,所以我们还可以试试
transfrom 的方法:

使用伪元素配合 transform 进行渐变动画,通过元素的伪元素 before 或者
after ,在元素内部画出一个大背景,再通过 transform
对伪元素进行变换:

JavaScript

div { position: relative; overflow: hidden; width: 100px; height: 100px;
margin: 100px auto; border: 2px solid #000; &::before { content:
“”; position: absolute; top: -100%; left: -100%; bottom: -100%; right:
-100%; background: linear-gradient(45deg, #ffc700 0%, #e91e1e 50%,
#6f27b0 100%); background-size: 100% 100%; animation: bgposition 5s
infinite linear alternate; z-index: -1; } } @keyframes bgposition { 0% {
transform: translate(30%, 30%); } 25% { transform: translate(30%, -30%);
} 50% { transform: translate(-30%, -30%); } 75% { transform:
translate(-30%, 30%); } 100% { transform: translate(30%, 30%); } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
div {
    position: relative;
    overflow: hidden;
    width: 100px;
    height: 100px;
    margin: 100px auto;
    border: 2px solid #000;
 
    &amp;::before {
        content: "";
        position: absolute;
        top: -100%;
        left: -100%;
        bottom: -100%;
        right: -100%;
        background: linear-gradient(45deg,  #ffc700 0%, #e91e1e 50%, #6f27b0 100%);
        background-size: 100% 100%;
        animation: bgposition 5s infinite linear alternate;
        z-index: -1;
    }
}
 
 
@keyframes bgposition {
    0% {
        transform: translate(30%, 30%);
    }
    25% {
        transform: translate(30%, -30%);
    }
    50% {
        transform: translate(-30%, -30%);
    }
    75% {
        transform: translate(-30%, 30%);
    }
    100% {
        transform: translate(30%, 30%);
    }
}
 

实现原理如下图所示:

正规网赌平台 9

我们可以在任意 animation 动画过程中再加入 scaleskewroate
等变换,让效果看上去更加逼真随机。效果如下:

See the Pen
伪元素配合transform实现背景渐变
by Chokcoco (@Chokcoco) on
CodePen.

上面列出来的只是部分方法,理论而言,伪元素配合能够产生位移或者形变的属性都可以完成上面的效果。我们甚至可以运用不同的缓动函数或者借鉴蝉原则,制作出随机性十分强的效果。

当然,本文罗列出来的都是纯 CSS 方法,使用 SVG 或者 Canvas
同样可以制作出来,而且性能更佳。感兴趣的读者可以自行往下研究。

背景图片

接下来, 我们可以添加一些样式并设置背景图片位置:

正规网赌平台 10

CSS

.fave { width: 70px; height: 50px; background:
url(images/twitter_fave.png) no-repeat; background-position: 0 0; }

1
2
3
4
5
6
.fave {
  width: 70px;
  height: 50px;
  background: url(images/twitter_fave.png) no-repeat;
  background-position: 0 0;
}

加了悬停状态后,一旦鼠标悬停在该元素上,背景就会从我们指定的位置移动到这一系列图片中最后一张的位置上(为了兼容浏览器,注意要添加相应的浏览器内核前缀——译者注)。

CSS

.fave:hover{ animation: fave 1s steps(55); } @keyframes fave{ 0%{
background-position:0 0; } 100%{ background-position:-3519px 0; } }

1
2
3
4
5
6
7
8
9
10
11
.fave:hover{
  animation: fave 1s steps(55);
}
@keyframes fave{
  0%{
    background-position:0 0;
  }
  100%{
    background-position:-3519px 0;
  }
}

请注意第1个规则 animation。在本例中,我们利用 steps
时序函数,让background-position 属性经历了一个持续时间为1秒的过渡。在
steps 部分的“55”这个值,代表了这段动画是由55帧组成的。

当我们将鼠标悬停在这个元素上时,所看到的效果是其背景图片通过55个相同的步骤经历了一次过渡。

另外这个案例,也可以用 transition 实现:

CSS

.fave:hover { background-position: -3519px 0; transition: background 1s
steps(55); }

1
2
3
4
.fave:hover {
  background-position: -3519px 0;
  transition: background 1s steps(55);
}

运用背景色渐变动画

背景色渐变动画具体可以运用在什么地方呢,稍微举个例子。

相关文章