CSS3学习之Animation

CSS3中的 Animation 可以让我们脱离Flash/js/jQuery等作一些简单的动画效果,虽然相对来说可能粗糙一些;另外,与HTML5中的canvas绘制的动画不同,CSS3的 Animation 效果只能应用在已存在的HTML DOM元素上。

CSS3 Animations

CSS动画实际上就是将计算得到的属性值应用到目标元素上,在整个动画的执行过程中,属性值的计算由动画控制,计算得到的属性值会覆盖普通样式系统(如CSS样式)先前的定义,动画会覆盖所由的样式规则,除了指定了 !important 的样式。

CSS3动画涉及到两个CSS属性:animation@keyframes ,它们的浏览器兼容情况如下表所示:

Property Chrome IE Firefox Safari Opera
animation 43.0
4.0 -webkit-
10.0 16.0
5.0 -moz-
9.0
4.0 -webkit-
30.0
15.0 -webkit-
12.0 -o-
@keyframes 43.0
4.0 -webkit-
10.0 16.0
5.0 -moz-
9.0
4.0 -webkit-
30.0
15.0 -webkit-
12.0 -o-

animation

transition 属性类似,CSS3动画中的 animation 属性也是一个简写属性,它们的作用都是随着时间改变元素的属性值;主要区别是 transition 需要触发一个事件(hover或click事件等)才会随时间改变其css属性,而 animation 不需要触发任何事件也可以显式的随着时间变化来改变元素的css属性值,从而达到一种动画的效果。

animation 属性相对来说更复杂一些,其语法如下:

1
animation: name duration timing-function delay iteration-count direction fill-mode play-state;

既然 animation 属性也是一个简写属性,那么其属性值也有一一对应的独立属性,后面的章节会详细介绍这些属性,在这只是简单地列举说明一下:

属性 说明
animation-name 指定动画名称,在 @Keyframes 中定义
animation-duration 元素播放动画所持续的时间,单位为s(秒)默认值为“0”
animation-timing-function 指定时间曲线函数,与 transition-time-function 用法一样
animation-delay 指定动画开始的延迟,默认值为0
animation-iteration-count 指定元素播放动画的循环次数,默认值为1
animation-direction 指定元素动画播放的方向,默认值为normal
animation-fill-mode
animation-play-state 用来控制元素动画的播放状态,默认值为running

使用CSS3动画时,一定要指定 animation-duration 属性,否则因为其默认值为0,动画永远也不会执行

keyframes

keyframes 是CSS3 Animation中的一个重要概念,可以理解为“关键帧”,这与Flash中的“关键帧”是一个意思。

keyframes用来指定在动画持续时间内的多个时间点上参与动画的属性值,keyframes指定了一个动画周期的行为,animation属性将该动画迭代一次或多次。

keyframes使用专门的规则来定义,其命名由 @keyframes 开头,后面紧接着是“动画名称”(该名称会被 animation-name 属性引用)和一对花括号“{}”,括号中就是一些不同时间段样式规则,其语法如下所示:

1
@keyframes animation-name {keyframes-selector {css-styles;}}

上面的语法伪代码中,所有值都是必须的,其中 animation-name 用来指定动画名字;css-styles 指定一个或多个变化的CSS属性;比较难理解的只有 keyframes-selector,是用来分隔动画持续时间的。

keyframes-selector 其实是动画持续时间的百分比,即把整个动画分成多段,其取值要在[0%,100%]区间内,负值或大于100%的数会被忽略;除了百分比外还可以使用“from”和“to”关键字,其中“from”等于“0%”,“to”等于“100%”。

keyframes-selector 使用百分比时,“%”号是必须的,即使是“0%”也不能丢掉“%”号

我们可以这样理解,每个 keyframes-selector 其实是一个时间点,从动画开始到结束,在每个时间点对目标元素指定不同的CSS样式;这些时间点将动画持续时间切分成多段,每段从起点到终点都有样式上的变化,也就是从起点到终点这段时间内,根据指定的计算函数(贝塞尔曲线)计算CSS样式值,然后应用到元素上,从而产生动画的效果。

就像百米赛跑,我们把100米分成三段0~30、30~80、80~100,共涉及到百米跑道上的四个位置点:0%、30%、80%和100%(这里的四个位置点可以想像成动画中的 keyframes)。第一段我们的速度是从0开始,加速到一定速度后稳定下来,中间50以稳定的速度跑下来,80米后要冲刺了,使出来吃奶的劲再加速,最后冲线。

animation-* 属性

animation-* 各属性的浏览器兼容情况如下表所示:

Property Chrome IE Firefox Safari Opera
animation-name 43.0
4.0 -webkit-
10.0 16.0
5.0 -moz-
9.0
4.0 -webkit-
30.0
15.0 -webkit-
animation-duration 43.0
3.0 -webkit-
10.0 16.0
5.0 -moz-
9.0
4.0 -webkit-
30.0
15.0 -webkit-
animation-timing-function 43.0
4.0 -webkit-
10.0 16.0
5.0 -moz-
9.0
4.0 -webkit-
30.0
15.0 -webkit-
animation-delay 43.0
4.0 -webkit-
10.0 16.0
5.0 -moz-
9.0
4.0 -webkit-
30.0
15.0 -webkit-
animation-iteration-count 43.0
4.0 -webkit-
10.0 16.0
5.0 -moz-
9.0
4.0 -webkit-
30.0
15.0 -webkit-
animation-direction 43.0
4.0 -webkit-
10.0 16.0
5.0 -moz-
9.0
4.0 -webkit-
30.0
15.0 -webkit-
animation-fill-mode 43.0
4.0 -webkit-
10.0 16.0
5.0 -moz-
4.0 -webkit- 15.0 -webkit-
12.1
animation-play-state 43.0
4.0 -webkit-
10.0 16.0
5.0 -moz-
9.0
4.0 -webkit-
30.0
15.0 -webkit-

Opera 浏览器从12.0开始可以通过加 -o- 前缀启动所有属性,这里没有展示

animation-name

animation-name 用来指定动画名称,默认为none,表示不采用动画效果;可以指定 @keyframes 定义的动画,如果名字匹配不到,那么元素将不会有动画效果。可以指定多个动画名称,之间用逗号分隔。

1
animation-name: <single-animation-name> [ ‘,’ <single-animation-name> ]*

animation-duration

animation-duration 指定动画执行一个完整周期所持续的时间,默认值为“0s”,不能为负值。

animation-timing-function

animation-timing-function 用来指定动画过程中CSS属性的变化速率曲线函数,与 transition-timing-function 基本上完全一样,不同之处就是 animation-timing-function 应用在keyframes分隔的每个时间段中,而不是整个动画。具体情况可参考 transition-timing-function

除了几个预置函数和 cubic-bezier() 自定义函数外,animation-timing-function 还可以指定为以下几个值:

属性值 描述
steps(int,start|end) steps 函数指定了一个阶跃函数,第一个参数指定了时间函数中的间隔数量(必须是正整数);第二个参数可选,接受 start 和 end 两个值,指定在每个间隔的起点或是终点发生阶跃变化,默认为 end。
step-start 相当于steps(1, start)
step-end 相当于steps(1, end)

steps(int,start|end) 函数略微复杂,暂时不去深究了,列几个参考:

animation-delay

animation-delay 属性用来指定动画开始的时间,属性值是一个数值,单位是秒(s),表示动画应用后多久后开始执行动画,默认值“0s”表示动画立即开始。

animation-iteration-count

animation-iteration-count 属性用来指定动画周期执行的次数,默认值为“1”,表示动画执行一次后就再执行了;除了设置为具体整数表示执行次数外,还可以使用“infinite”关键字,表示动画将一直循环,永不停歇;设置为小数会导致动画中途停止;负值是不被允许使用的。

此属性经常配合 animation-direction 值设置为 alternate 时一起使用,这会产生动画正向和反向交替进行的效果。

animation-direction

animation-direction 属性用来指定动画播放的“方向”,这里的“方向”意思是 Keyframes 中定义的动画顺序,“正向”表示按 Keyframes 中定义的动画顺序执行,即0%执行到100%,“反向”表示按与 Keyframes 定义相反的动画顺序执行。

animation-direction 属性可以设置为以下值:

属性值 说明
normal 默认值,动画每次播放都“正向”播放
alternate 动画播放时,奇数次“正向”播放,偶数次“反向”播放
reverse normal 相反,动画每次播放都“反向”播放
alternate-reverse alternate 相反,奇数次“反向”播放,偶数次“正向”播放
  • 迭代次数从 1 开始计数
  • 动画反向运行时,animation-timing-function 也会反向,例如正向如果是 ease-in 函数效果的动画,那反向就会使用 ease-in 函数的效果

animation-fill-mode

animation-fill-mode 属性指定动画没有执行时(动画完成后或执行前)元素的样式,默认情况下,CSS动画在被应用(animation-name 属性被设置到元素上)到开始运行期间(这段时间由 animation-delay来定义)和动画运行结束后这两个时间不会给元素应用任何样式,而 animation-fill-mode 属性可以覆盖这种行为。

animation-fill-mode 属性可以设置为以下值:

属性值 说明
none 默认值,动画不会对动画等待和动画完成时的元素样式产生改变
forwards 动画结束后,元素的样式将设置为动画的最后一帧的样式
backwards 动画等待执行的时间内,元素的样式将设置为动画第一帧的样式
both 同时应用forwards和backwards两个属性值的效果,意味着在动画等待和动画结束状态,元素将分别应用动画第一帧和最后一帧的样式

理解animation-fill-mode属性

animation-play-state

animation-play-state 属性定义动画的播放状态(“运行中”或“暂停”),它只有两种状态:runningpaused,默认值是”running”;运行中的动画可以通过设置该属性值为”paused”来暂停动画,恢复暂停的动画可以将属性值设置为”running”。

暂停的动画可以从元素当前状态恢复运行,就像时间静止了一样,也就是说,当暂停的动画恢复时,它会从暂时时的状态继续播放,而不是从动画的初始状态重新播放。

CSS动画示例

有些知识示例演示可以更好地理解,另外在写代码的时候也可以发现一些细节问题;下面就用几个例子尽可能覆盖上面提到的所有CSS3动画相关属性。

简单地移动

下面是个极其简单的动画示例,一个红色的DIV块在4秒时间内向右移动240像素,并无限循环。虽然代码简单,但包含了CSS3动画所需的所有内容,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@keyframes moving-div {
from {left: 0px}
to {left: 240px}
}
.animation-demo-box {
width: 90px;
height: 90px;
background: red;
position: relative;
color: white;
margin-bottom: 2px;
}
.animation-demo-0 {
animation: moving-div 4s infinite;
}
动起来…

在一些网络博客上,会将动画名字用引号包起来(可能是年代久远的缘故),经测试这里不能用引号,也就是说 @keyframes moving-div 不能写成 @keyframes "moving-div";引用时也不能加引号,即 animation-name: moving-div 不能写成 animation-name: "moving-div"

摇摆

在上面示例的基础上增加 animation-direction: alternate 后效果如下所示:

1
2
3
4
5
6
7
.animation-demo-1 {
animation-name: moving-div;
animation-duration: 4s;
animation-delay: 3.5s;
animation-direction: alternate;
animation-iteration-count: infinite;
}
动起来…

可以看到本例中的元素会来回摇摆,并不像上面那个到右边后会立即恢复到初始值,结合 animation-direction 部分的解释可以了解,animation-direction: alternate 的意思就是奇数次迭代会从 @keyframes 中定义的“from”到“to”运动(即正向),偶数次迭代会从“to”到“from”运动(即反向),演示效果可以很好地说明这点。

由于增加了 animation-delay: 3.5s,所以方块会在3.5秒后才开始执行动画,如果动画已经运行了,刷新一下试试。

另外,从该示例也可以看到,在反向运行时,animation-timing-function 也会反向,例子中向右运动(正向)时方块会先快后慢,而向左运动(反向)时却是先慢后快,由于 animation-timing-function 跟随反向的存在,整个动画显得很流畅。

动画的状态

本示例演示一下 animation-play-state 属性的作用,为了运行过程中改变元素的 animation-play-state 属性值,这个示例使了Javascript代码,如下所示:

1
2
3
.animation-demo-2 {
animation: moving-div 3s infinite alternate paused;
}
1
2
3
4
5
6
7
8
9
10
function changePlayState(btn) {
var el = document.getElementById('animation-demo-2');
if (el.style.animationPlayState != 'running') {
el.style.animationPlayState = 'running';
btn.innerText = "暂停动画";
} else {
el.style.animationPlayState = 'paused';
btn.innerText = "启动动画";
}
}

动起来…

通过 changePlayState 方法代码可知,点击按钮会使方块的 animation-play-state 属性值在 pausedrunning 两种状态之间来回切换,方块初始状态是暂停的(animation-play-state 属性值为 paused),点击按钮方块移动,再次点击方块停止移动,如此往复。

这个示例的效果与 animation-play-state 部分描述的一致,也很好地说明 暂停的动画可以从元素当前状态恢复运行 这句话的意思,动画的暂停与恢复非常流畅。

时间曲线函数

本例用来演示不同 animation-timing-function 的效果,除了下面演示的还可以使用 cubic-bezier() 函数自定义,这与 transition-timing-function 一样,不再描述。

1
animation: moving-div 3s 1s linear infinite;
1
2
3
4
5
6
7
8
9
var funArray = ['ease', 'ease-in', 'ease-out', 'ease-in-out', 'linear']
function changeTimingFunction(btn) {
var el = document.getElementById('animation-demo-3');
var curFun = el.style.animationTimingFunction;
if (curFun) funArray.push(curFun);
var targetFun = funArray.shift();
el.style.animationTimingFunction = targetFun;
btn.innerText = targetFun;
}

动起来…

可以看到

填充模式

本示例演示 animation-fill-mode 各值的区别,一需要结合 animation-fill-mode 部分的解释来看。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@keyframes fillMode {
from {background-color: green;}
to {
transform: translateX(300px) scaleY(.6);
background: blue;
}
}
.fill-mode-demo-1 {
animation: fillMode 4s 2s;
}
.fill-mode-demo-2 {
animation: fillMode 4s 2s forwards;
}
.fill-mode-demo-3 {
animation: fillMode 4s 2s backwards;
}
.fill-mode-demo-4 {
animation: fillMode 4s 2s both;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function start() {
let els = document.querySelectorAll("div[class*='hadReset']");
let index = 1;
for(let el of els) {
el.classList.add(`fill-mode-demo-${index++}`);
el.classList.remove('hadReset');
}
}
function reset() {
let els = document.querySelectorAll("div[class*='fill-mode']");
let index = 1;
for(let el of els) {
el.classList.remove('fill-mode-demo-'+index);
el.classList.add('hadReset');
index++;
}
}

none
forwards
backwards
both

本示例为了更好地演示 animation-fill-mode 各值的效果,特意给动画增加了一个2秒的延时,四个示例从上到下依次是 ‘none’、’forwards’、’backwards’和’both’的效果;四个动画在执行时完全一样,只有在执行前(延时期间)和执行结束有样式上的区别,仔细多看几遍就能明白其区别。

可以看到,第一个动画(none)在动画执行前和结束后元素样式都是初始状态,即动画不会给元素设置样式;第二个动画(forwards)在动画执行结束后,元素保持动画最后一帧的样式;第三个动画(backwards)在动画执行前(点击“开始”按钮后的2秒延时)直接应用动画第一帧的样式,动画执行结束后恢复到初始样式;第四个动画(both)集成了第二、第三两个动画的效果,执行前应用动画第一帧样式,执行结束应用动画最后一帧样式。

这里的四个动画效果可以很好地与 animation-fill-mode 部分的解释一一对应起来。

发光的按钮

最后放一个比较状态较复杂的动画效果,是一个发光的按钮,其实逻辑并不复杂,只是关键帧较多。

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
@keyframes buttonLight {
from {
background-color: rgba(96, 203, 27,0.5);
color: red;
box-shadow: 0 0 5px rgba(255, 255, 255, 0.3) inset, 0 0 3px rgba(220, 120, 200, 0.5);
}
25% {
background-color: rgba(196, 203, 27, 0.8);
color: blue;
box-shadow: 0 0 10px rgba(255, 155, 255, 0.5) inset, 0 0 8px rgba(120, 120, 200, 0.8);
}
50% {
background-color: rgba(196, 203, 127, 1);
color: orange;
box-shadow: 0 0 5px rgba(155, 255, 255, 0.3) inset, 0 0 3px rgba(220, 120, 100, 1);
}
75% {
background-color: rgba(196, 203, 27, 0.8);
color: red;
box-shadow: 0 0 10px rgba(255, 155, 255, 0.5) inset, 0 0 8px rgba(120, 120, 200, 0.8);
}
to {
background-color: rgba(96, 203, 27,0.5);
color: green;
box-shadow: 0 0 5px rgba(255, 255, 255, 0.3) inset, 0 0 3px rgba(220, 120, 200, 0.5);
}
}
.animation-demo-10 {
background: #60CB1B;
border-radius: 5px;
color: #FFF;
font-size: 16px;
font-weight: bold;
padding: 10px 15px;
text-decoration: none;
animation-name: buttonLight;
animation-duration: 5s;
animation-iteration-count: infinite;
}

我会发光

文章目录
  1. 1. CSS3 Animations
    1. 1.1. animation
    2. 1.2. keyframes
  2. 2. animation-* 属性
    1. 2.1. animation-name
    2. 2.2. animation-duration
    3. 2.3. animation-timing-function
    4. 2.4. animation-delay
    5. 2.5. animation-iteration-count
    6. 2.6. animation-direction
    7. 2.7. animation-fill-mode
    8. 2.8. animation-play-state
  3. 3. CSS动画示例
    1. 3.1. 简单地移动
    2. 3.2. 摇摆
    3. 3.3. 动画的状态
    4. 3.4. 时间曲线函数
    5. 3.5. 填充模式
    6. 3.6. 发光的按钮
|