今年我面试了不少同窗,只要看到简历上写“熟练掌握CSS3”的,我都会问问动画相关知识。然而我发现:都 2019
年了,还有不少同窗不会 CSS
动画。css
我常常爱问的一个问题是,实现以下的效果:面试
即,一个小球从向右匀速移动 200px
,而后移动回来,再移动过去,最后停留在 200px
处。canvas
动图效果以下:
浏览器
就是需求这么简单的一个动画,然而绝大多数人却不能答对。app
不卖关子,个人答案是:函数
div{
width: 40px;
height: 40px;
border-radius: 50%;
background: #0ff;
animation: move 2s linear 3 alternate both;
}
@keyframes move{
0%{
transform: translate(0,0);
}
100%{
transform: translate(200px,0);
}
}
复制代码
大部分面试者说,关于 CSS
动画,也看过一些教程,工做中却不怎么使用,所以就忘了。工具
这里,我准备为对 CSS
动画掌握不深的小伙伴补充一下相关知识。欢迎大佬们拍板。动画
正文开始。网站
经过开发者工具能够发现,animation
(动画)属性是 8 个属性的简写。ui
这 8 个属性具体含义以下:
属性 | 描述 |
---|---|
animation-duration | 指定动画完成一个周期所须要时间,单位秒(s)或毫秒(ms),默认是 0。 |
animation-timing-function | 指定动画计时函数,即动画的速度曲线,默认是 "ease"。 |
animation-delay | 指定动画延迟时间,即动画什么时候开始,默认是 0。 |
animation-iteration-count | 指定动画播放的次数,默认是 1。 |
animation-direction | 指定动画播放的方向。默认是 normal。 |
animation-fill-mode | 指定动画填充模式。默认是 none。 |
animation-play-state | 指定动画播放状态,正在运行或暂停。默认是 running。 |
animation-name | 指定 @keyframes 动画的名称。 |
下面咱们一个个仔细说明,各个动画属性都是用来作什么的,以及须要注意的地方。
CSS
动画,也称关键帧动画。经过 @keyframes
来定义关键帧。
帧的概念,想必你们很清楚,好比电影就是一帧帧图片在播放,利用图像在人脑中短期停留来造成动态效果。CSS
动画也是利用这个原理。不过开发者不须要给出每一帧的定义。只须要定义一些关键的帧便可。由于其他的帧,浏览器会根据计时函数插值计算出来。
好比咱们一个 div
旋转一圈,只须要定义开始和结束两帧便可:
@keyframes rotate{
from{
transform: rotate(0deg);
}
to{
transform: rotate(360deg);
}
}
复制代码
其中,rotate
是我给这个动画起的名字,from
表示最开始的那一帧,to
表示结束时的那一帧。
准确地说,CSS
动画用百分比来刻画一个动画周期,from
实际上是 0%
的别称,to
是 100%
的别称。所以关键帧 rotate
等价于:
@keyframes rotate{
0%{
transform: rotate(0deg);
}
100%{
transform: rotate(360deg);
}
}
复制代码
定义好了关键帧后,下来就能够直接用它了:
animation: rotate 2s;
复制代码
或者:
animation-name: rotate;
animation-duration: 2s;
复制代码
经过 animation-name
来指定动画使用的关键帧,这个是必须的。用 JS
来理解的话,至关于:只有变量声明是不行的,还须要使用。
另外上述代码还指定了动画运行的时间 animation-duration
为 2s
。最后运行效果以下:
动图的效果不是太明显,方块在旋转时,不是匀速的。由于此时刻画动画速度的属性 animation-timing-function
默认值是 ease
,即先快后慢。
下面动图演示了计时函数属性一些值的情形:
animation-timing-function
常见值有:linear
、ease
、ease-in
、ease-out
、ease-in-out
。这些值其实都是 cubic-bezier(n,n,n,n)
的特例。它们被称为贝塞尔曲线。除了开发者工具外,《CSS揭秘》做者也写了的一个在线调试贝塞尔曲线的网站:cubic-bezier.com。贝塞尔曲线这个知识点颇有用,canvas
里也有相应的 API
。能够展开的点其实比较多,这里只是初步介绍。
须要提一下,计时函数属性另外的一个好玩的值是 steps
函数,能够用来实现逐帧动画:
计时函数属性介绍到此,后面一概使用值 linear
,即表示匀速动画。
回到关键帧,咱们除了指定开头和结束位置的关键帧(若是不指定 0%
和 100%
,浏览器会自动推断),固然也能够指定任意百分比的帧是什么状况,好比开篇例子的另外一种实现:
div{
width: 40px;
height: 40px;
border-radius: 50%;
background: #0ff;
animation: move 6s linear both;
}
@keyframes move{
0%{
transform: translate(0,0);
}
33%{
transform: translate(200px,0);
}
66%{
transform: translate(0,0);
}
100%{
transform: translate(200px,0);
}
}
复制代码
关键帧代码有冗余,能够进一步简写:
@keyframes move{
0%, 66%{
transform: translate(0,0);
}
33%,100%{
transform: translate(200px,0);
}
}
复制代码
此时,动画时长改为了 6s
,动画进行到三分之一处时,让 div
位于 200px
,三分之二回到开始位置,结束时移动到 200px
处。
这种是比较直观的实现方式,有不少面试者通常都会想到这种。
注意 animation: move 6s linear both;
声明中的 both
。它是属性 animation-fill-mode
的一个值。这个属性容易被忽略,然而倒是 CSS
动画比较重要的一个属性。直译为动画填充模式,具体说的是什么事情呢?
@keyframes
只是定义了动画过程当中每一帧的值,然而在动画开始前和动画结束后,元素改处于什么状态呢?animation-fill-mode
说的就是这个事情。除了默认值 none
外,还有另外 3 个值:
举个例子,div
从 100px
处移动到 200px
处的关键帧定义为:
@keyframes move{
0%{
transform: translate(100px,0);
}
100%{
transform: translate(200px,0);
}
}
复制代码
设置填充模式为 forwards
时,动画最后停留在 200px
处:
设置动画延迟 1s
后执行,且填充模式为 backwards
时,能够看到动画在开始前是处于 100px
处,动画结束后回到 0px
处:
最后设置填充模式为 both
的情形:
动画结束后,保持动画最后一帧的状态,这个太有用了,好比咱们能够实现一个进度条:
div{
height: 10px;
border: 1px solid;
background: linear-gradient(#0ff,#0ff);
background-repeat: no-repeat;
background-size: 0;
animation: move 2s linear forwards;
}
@keyframes move{
100%{
background-size: 100%;
}
}
复制代码
效果以下:
上面提到了可使用 animation-delay
设置延迟时间。不为你们注意的是,延迟能够为负数。负延迟表示动画仿佛开始前就已经运行过了那么长时间。
拿上述进度条为例子,原动画用了 2s
是从 0%
加载到 100%
的。若是设置延迟为 -1s
。这动画会从 50%
加载到 100%
。仿佛已经运行了 1s
同样:
CSS
动画是能够暂停的。属性 animation-play-state
表示动画播放状态,默认值 running
表示播放, paused
表示暂停:
animation-play-state
这个属性很是好用,它能够与负延迟一块儿实现特殊的效果,好比进度条插件:
目前为止还有两个属性没有介绍,一个是 animation-iteration-count
表示动画播放次数。它很好懂,只有一点要注意,无限播放时使用 infinite
。另外一个是播放方向 animation-direction
,它的意思说指定动画按照指定顺序来播放 @keyframes
定义的关键帧。其值有:
示意以下:
animation
属性以及 8 个子属性介绍完了,另外须要说明的是它们与 background
及其各子属性同样,是支持多个值的,即在同一个元素上应用多个动画,送给你们一个如意金箍棒:
<style>
div{
margin: 200px;
height: 20px;
border: 1px solid;
animation: rotate 2.5s infinite, color 2s infinite, width 3s infinite;
animation-direction: normal, normal, alternate;
}
@keyframes rotate {
100%{
transform: rotate(360deg);
}
}
@keyframes color {
20%{
background-color: #f91;
}
80% {
background-color: #0ff
}
}
@keyframes width {
0% {
width: 40%;
}
100% {
width: 70%;
}
}
复制代码
效果以下:
本文完。