11.5 CSS 动画(animations)
我们前面提到过,转换(transitions) 实际上就是一种特殊的CSS动画:
- 只有两个状态: 起始状态和终止状态
- 动画不会出现循环
- 中间状态只能由时变函数(transition-timing-function)来控制
实际动画需求要复杂得多,比如我们可能会需要:
- 自动播放的动画(不会有交互状态)
- 控制中间状态
- 创建循环动画
- 在同一个HTML元素上应用不同的动画
- 在动画过程中控制不同的元素属性
- 给不同的属性应用不同的时变函数
这个时候就需要使用CSS3动画(animation)特性,而且提供了更多的功能。
CSS3动画就像一部迷你电影,里面有演员(HTML元素)、剧本(keyframes)以及动作片段(CSS规则)。
animation 属性
和 transition
属性一样,animation
是一组动画属性的速写:
- name: 动画名称
- duration: 动画持续时间
- timing-function: 时变函数,用来计算中间状态
- delay: 延时,在一定时候后启动动画
- iteration-count: 动画重复的次数
- direction: 动画的运行方向,可以是反过来的
- fill-mode: 动画填充模式,用来确定动画开始之前和结束之后的样式
例1:提示信息自动淡出动画
代码很简单,就是把keyframes(下面会讲解)的最后一帧设置为透明,持续时间3s。为了演示,我们把animation的循环模式设置为infinite。实际使用时需要修改为forwards,即停留在最后的状态。
例2:按钮弹跳动画
我们给一个按钮添加弹跳(bouncing)动画:
@keyframes bouncing{
0% { bottom: 0; box-shadow: 0 0 5px rgba(0,0,0,0.5);}
100%{ bottom: 50px; box-shadow: 0 50px 50px rgba(0,0,0,0.1);}
}
.loading-button{ animation: bouncing 0.5s cubic-bezier(0.1,0.25,0.1,1) 0s infinite alternate both;}
Loading首先我们选定“演员”为一个加载按钮(html元素),然后设定其表演剧本(keyframes)为弹跳,然后添加一些动作指令(CSS规则)来创建一个CSS3动画:
- name: bouncing (动画名称必须和keyframes名称一致)
- duration: 0.5s (持续0.5秒)
- timing-function: cubic-bezier(0.1,0.25,0.1,1)
- delay: 0s (没有延迟)
- iteration-count: infinite (无限循环)
- direction: alternate (交替往返)
- fill-mode: both(填充模式同时应用backwards和forwards规则,后面会详细说明)
@keyframes
在“电影开拍”之前,我们得创建“剧本”(@keyframes,即关键帧),用来规定动画中间的每一个表演步骤。@keyframes通过percentages(百分比格式的时间坐标)来定义:
0%
动画的第一帧(可选)。50%
动画的中间时间节点。100%
动画的最后一帧。
我们也可以分别使用关键词 from
和 to
来代替 0%
和 100%
。
你可以定义任意多的keyframes,比如 33%
, 4%
乃至 29.86%
。
每个 keyframe 都是一个 CSS规则,定义这个时间节点下元素的某个或某些属性。
@keyframes
具体语法定义如下:
@keyframes animationname {keyframes-selector {css-styles;}}
- animationname: 必需。定义动画的名称。
- keyframes-selector: 必需。百分比格式的时间坐标。合法的值:0-100% | from(与 0% 相同)| to(与 100% 相同)。
- css-styles: 必需。一个或多个合法的 CSS规则(样式定义)。
@keyframes around {
0% { left: 0; top: 0;}
25% { left: 240px; top: 0;}
50% { left: 240px; top: 240px;}
75% { left: 0; top: 240px;}
100%{ left: 0; top: 0;}
}
p{ animation: around 4s linear infinite;}
上面的例子把起点 0%
和终点 100%
设置成一样的状态,并且是 infinite
播放,这样可以确保动画的两次播放之间的无缝衔接。
另外如果若干时间节点具有相同的样式,可以合并在一起简写,比如:
@keyframes around {
0%, 100% { left: 0; top: 0;}
}
如果在@keyframes中0%和100%时间点所设置的属性有默认值,那么有些情况下可以忽略不写。
动画名称(animation-name)
动画名称(animation-name)会至少出现两次:
- 一次是“编写剧本”
@keframes
时。 - 一次是“演员入戏”时,即设置HTML元素的
animation-name
属性值为“剧本”的名称(或者在animation
速写中)。
@keyframes scenario{
/* ... */
}
.selector{ animation-name: scenario;}
和CSS class名称一样,animation 的名称只能包含:
- 字母 (a-z)
- 数字 (0-9)
- 下划线 underscore (_)
- 中划线 dash (-)
不能以数字或者两个中划线开始。
动画持续时间(animation-duration)
和 transition durations 一样,animation durations 可以设置为 秒 1s
或 毫秒 200ms
。
.selector{ animation-duration: 0.5s;}
默认值为 0s
,即不会有动画出现。
动画时变函数(animation-timing-function)
和 transition timing functions 一样,animation timing functions 可以使用一些预定义的关键词比如 linear
, ease-out
, 或者使用cubic bezier函数来自定义。
.selector{ animation-timing-function: ease-in-out;}
缺省值是 ease
。
我们可以通过设置线性时变函数以及自定义的@keyframes来模拟复杂的贝塞尔曲线。Bounce.js 就是这样一个在线高级动画生成工具,支持导出CSS样式代码。
animation-delay
和 transition delays 一样,animation delays 可以设置为 秒 1s
或 毫秒 200ms
。
默认值为 0s
,即不会有延迟。
这个属性在触发多个时间交替的动画序列时很有用。
.a,.b,.c{ animation: bouncing 1s;}
.b{ animation-delay: 0.25s;}
.c{ animation-delay: 0.5s;}
动画循环次数(animation-iteration-count)
默认情况下,动画只运行一次(即默认值为 1),你可以设置3种类型的数值:
- 整数 如
2
或3
- 小数 如
0.5
,意味着只运行动画的一半 - the 关键词
infinite
无限重复
.selector{ animation-duration: infinite;}
动画方向(animation-direction)
animation-direction 定义浏览器对@keyframes的读取顺序。
- normal: 正常方向,从
0%
开始,到100%
结束,然后再从0%
开始。 - reverse: 相反方向,从
100%
开始,到0%
结束,然后再从100%
开始。 - alternate: 交替方向,从
0%
开始,到100%
,再到0%
。 - alternate-reverse: 反向交替方向,从
100%
开始,到0%
,再到100%
。
通过下面的循环动画,对比小方块的运动轨迹,可以比较直观的感受这几个方向取值之间的差别:
Normal: 0% --> 100%
Reverse: 100% --> 0%
Alternate: 0% <--> 100%
Alternate reverse: 100% <--> 0%
动画填充模式(animation-fill-mode)
animation-fill-mode 用来确定动画开始之前和结束之后的状态。这样才是一个完整的动画过程。
通过 keyframes 我们定义了动画不同阶段下的CSS规则,这有可能会和已经定义的样式冲突。
填充模式属性允许我们告诉浏览器是否动画样式在动画之外也生效。
让我们想象这样一个按钮:
- 默认是红色
- 在动画开始时被设置为绿色
- 在动画结束时被设置为蓝色
animation-fill-mode | 动画开始前 | 动画开始时 | 动画结束时 | 动画结束后 |
---|---|---|---|---|
none | Default | Start | End | Default |
forwards | Default | Start | End | End |
backwards | Start | Start | End | Default |
both | Start | Start | End | End |
1. 动画之前 2. 动画期间 3. 动画之后
None: 动画样式不会影响默认样式
缺省为红色 从蓝变绿 变回缺省红色
Forwards: 动画结束时的样式被保持到动画结束后
缺省为红色 从蓝变绿 保持绿色
Backwards: 动画开始时的样式会被预置到动画开始前(即默认样式会被覆盖)
总是蓝色 从蓝变绿 变回缺省红色
Both: 动画开始时的样式会被预置到动画开始前,动画结束时的样式被保持到动画结束后
总是蓝色 从蓝变绿 保持绿色
我们可以简单的理解为:forwards就是动画样式作用区间向时间轴正方向(->)延伸,backwards则向负方向(<-)延伸,而both就是双向()延伸。从而影响到相邻区间的默认样式。