基本了解
css中实现动画有两种方式:transition
过渡动画、 animation
自定义动画。
本文主要讲解animation
动画的使用,若要了解transition
过渡动画请前往transition过渡动画。
我们先简单了解下animation的一些语法和使用过程,后面会详细解说:
- 通过
@keyframes
自定义关键帧动画并为动画命名,可以在其中对每一帧进行设置。
- 使用自定义动画的元素,需要通过
animation
相关属性进行配置
- animation-name
- animation-duration
- animation-timing-function
- animation-delay
- animation-iteration-count
- animation-direction
- animation-fill-mode
- animation-play-state
我们还可在JavaScript中,通过驼峰式命名来访问/设置animation
相关属性。
@keyframes
keyframes(关键帧),在css样式表中可以通过@keyframes
来设置关键帧动画,并指定动画名称供使用者锁定。
其语法如下:
我们可以通过百分比来设置具体帧数的样式。
1 2 3 4 5
| @keyframes animateName{ 0% { width:50px; height:50px; } 50% { width:100px; height:100px; } 100% { width:50px; height:50px; } }
|
0%
和100%
代表首尾帧
,也可分别使用from
、to
替代。下面代码与上述代码效果相同
1 2 3 4 5
| @keyframes animateName{ from { width:50px; height:50px; } 50% { width:100px; height:100px; } to { width:50px; height:50px; } }
|
需要注意的是: 若自定义动画未定义首尾帧,则首尾帧将会应用使用者的原有样式
现在动画定义完毕,使用者需要配置animation
相关属性对动画进行配置。
animation-name
若某个元素想要使用对应名称的动画,需要配置animation-name: animateName
属性进行锁定。
下面以一个简单的动画为例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <style> .box { width: 50px; height: 50px; background-color: pink; animation-name: test; animation-duration: 1s; animation-iteration-count: infinite; } @keyframes test { 50% { width: 100px; height: 100px; border-radius: 50%; background-color: skyblue; } } </style> <body> <div class="box"></div> </body>
|
这里为了让动画更加明显,使用了animation-duration
与animation-iteration-count
,这里简单介绍一下:
animation-duration
用于定义动画持续时间,默认0s
animation-iteration-count
用于定义动画迭代次数,也就是执行次数,默认为1
。
animation-duration
animation-duration
顾名思义,用于设置动画持续时间.
需要注意的是:**默认值为0s
**,也就是说,若不配置animation-duration
则默认请况下是没有动画效果的,即便使用animation-name
锁定了动画名称,由于动画持续时间为0s
,所以没有效果。
animation-timing-function:
animation-timing-function
用于定义时间函数,通过这个选项,可配置动画随时间的运动速率和轨迹。
值 |
描述 |
linear |
动画从头到尾的速度是相同的。 |
ease(缓解) |
**默认值 **:动画以低速开始,然后加快,在结束前变慢。 |
ease-in |
动画以低速开始。 |
ease-out |
动画以低速结束。 |
ease-in-out |
动画以低速开始和结束。 |
cubic-bezier(n,n,n,n) |
贝塞尔曲线(自定义数值),可到相关网站可视化设置。 |
效果展示:
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
| <style> * { margin: 0px; padding: 0px; box-sizing: border-box; } body { width: 100vw; height: 100vh; display: flex; flex-direction: column; align-items: center; background-color: #34495e; } ul { display: flex; flex-direction: row; justify-content: center; list-style: none; display: flex; } ul > li { width: 40%; margin: 0px 40px; position: relative; } ul > li > .fa { font-size: 4em; color: white; opacity: 0.8; animation: test 2s infinite; } @keyframes test { to { transform: translateY(86vh); } } ul > li:nth-of-type(1) > .fa { animation-timing-function: linear; } ul > li:nth-of-type(2) > .fa { animation-timing-function: ease; } ul > li:nth-of-type(3) > .fa { animation-timing-function: ease-in; } ul > li:nth-of-type(4) > .fa { animation-timing-function: ease-out; } ul > li:nth-of-type(5) > .fa { animation-timing-function: ease-in-out; } ul > li:nth-of-type(6) > .fa { animation-timing-function: cubic-bezier(0.29, 1.69, 0.39, -0.05); } li > span { position: absolute; color: #f1c40f; } strong { color: #e67e22; margin: 10px; } </style> <body> <strong>animatin-timing-function:</strong> <ul> <li> <span>linear<br />线性</span> <div class="fa">👇</div> </li> <li> <span>ease<br />默认。动画以低速开始,然后加快,在结束前变慢。</span> <div class="fa">👇</div> </li> <li> <span>ease-in<br />以低速开始</span> <div class="fa">👇</div> </li> <li> <span>ease-out<br />以低速结束</span> <div class="fa">👇</div> </li> <li> <span>ease-in-out<br />以低速开始和结束</span> <div class="fa">👇</div> </li> <li> <span>cubic-bezier()<br />贝塞尔曲线(自定义数值)</span> <div class="fa">👇</div> </li> </ul> </body>
|
animation-delay
animation-delay
用于设置动画延迟时间,单位为s
下例动画将于2s
后执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| .box { width: 50px; height: 50px; background-color: pink; animation-name: test; animation-duration: 1s; animation-delay: 2s; } @keyframes test { 50% { width: 100px; height: 100px; border-radius: 50%; background-color: skyblue; } }
|
当同时使用多个动画时,这个属性使用频率非常高,可依次定义每个动画的延迟执行时间,区分开每个动画。
当然其实也可分别设置每个动画的其它animation族属性,后面会详细介绍多动画累加。
animation-iteration-count:
animation-iteration-count
用于设置动画执行的次数,默认值为1
只执行一次。
其值可分为两种:
- 具体number数值
infinite
:执行无限次
animation-direction
animation-direction
用于设置动画执行方向,具体来说可设置为以下值:
值 |
描述 |
normal |
默认值。动画按正常播放。 |
reverse |
动画反向播放。 |
alternate(交替的) |
动画正向交替执行(正向->反向)Loop。 |
alternate-reverse |
动画反向交替执行(反向->正向)Loop。 |
inherit |
从父元素继承该属性。 |
效果展示:
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
| <style> * { margin: 0px; padding: 0px; box-sizing: border-box; } body { width: 100vw; height: 100vh; display: flex; flex-direction: column; background-color: #34495e; justify-content: center; align-items: center; } ul { display: flex; flex-direction: row; list-style: none; width: 300px; height: 300px; justify-content: center; align-items: center; } ul > li { margin: 0px 40px; /* border: 2px solid #ddd; */ display: flex; flex-direction: column; color: #e74c3c; justify-content: center; align-items: center; } ul > li > .fa { animation: test 1.3s infinite; font-size: 7em; } ul li:nth-of-type(1) > .fa { animation-direction: normal; } ul li:nth-of-type(2) > .fa { animation-direction: reverse; } ul li:nth-of-type(3) > .fa { animation-direction: normal; } ul li:nth-of-type(4) > .fa { animation-direction: reverse; } @keyframes test { 100% { transform: scale(1.7); } } h1 { color: white; opacity: 0.8; } li > span { font-size: 24px; margin: auto; margin-top: 30px; } body ul:nth-of-type(2) li:nth-of-type(1) > .fa { animation-direction: alternate; } body ul:nth-of-type(2) li:nth-of-type(2) > .fa { animation-direction: alternate-reverse; } strong { font-size: 20px; color: white; opacity: 0.76; } </style> <body> <h1>animation-direction:</h1> <ul> <li> <div class="fa">❤</div> <span>normal</span> <p>默认值/正向</p> </li> <li> <div class="fa">❤</div> <span>reverse</span> <p>反向进行动画</p> </li> </ul> <strong >可以利用默认值normal和reverse,交叉动画的效果,<br />也可以正反向反复交替如下。</strong > <ul> <li> <div class="fa">❤</div> <span>alternate</span> <p>反复交替(正向)</p> </li> <li> <div class="fa">❤</div> <span>alternate-reverse</span> <p>反复交替(反向)</p> </li> </ul> </body>
|
animation-fill-mode
animation-fill-mode
用于设置动画的填充模式,主要应用的属性值为:
值 |
描述 |
none |
默认值。动画在动画执行前后,不会应用任何样式到目标元素。 |
forwards |
在动画结束后(由 animation-iteration-count 决定),目标元素将保持应用最后帧 动画。 |
backwards |
在动画结束后(由 animation-iteration-count 决定),目标元素将保持应用起始帧 动画。 |
案例测试:
下例代码,在动画执行结束后,将会一直应用最后帧的样式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| .box { width: 50px; height: 50px; background-color: pink; animation-name: test; animation-delay: 2s; animation-duration: 1s; animation-fill-mode: forwards; /* animation-iteration-count: infinite; */ } @keyframes test { 100% { width: 100px; height: 100px; border-radius: 50%; background-color: skyblue; } }
|
注意:上述代码若添加animation-iteration-count: infinite
,由于动画次数无限执行,不会结束,也就不会应用最后帧样式
animation-play-state
可设置动画的执行状态,通常通过JavaScript动态控制。
- 默认值为:
running
- 设为
paused
(暂停),动画将停止执行。
下面动画将不会执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| .box { width: 50px; height: 50px; background-color: pink; animation-name: test; animation-delay: 2s; animation-duration: 1s; animation-play-state: paused; //值为paused将不会执行 } @keyframes test { 50% { width: 100px; height: 100px; border-radius: 50%; background-color: skyblue; } }
|
通过JavaScript动态控制:
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
| <style> .box { width: 50px; height: 50px; background-color: pink; animation-name: test; animation-duration: 1s; animation-iteration-count: infinite; } @keyframes test { 50% { width: 100px; height: 100px; border-radius: 50%; background-color: skyblue; } } </style> <body> <div class="box"></div> <button onclick="operation('running')">开始</button> <button onclick="operation('paused')">停止</button> <script> function operation(mode) { document.querySelector("div").style.animationPlayState = mode; } </script> </body>
|
多动画累加
若元素应用多个动画,我们可以分别控制各个动画的一些属性,来达到区分各个动画的效果。
下面示例,给animation
族属性分别设置多个值,来对不同的动画做不同的配置。
animation
族属性设置多个值时,各个值之间使用,
隔开。
案例:
- 首先使用
animation-name
来锁定使用的各个动画
- 之后使用其它的
animation
族属性,分别约束对应动画,且设置顺序与animation-name
使用动画的顺序保持一致。
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
| <style> * { margin: 0px; padding: 0px; box-sizing: border-box; } body { background-color: #353b48; } main { display: flex; justify-content: center; align-items: center; width: 100vw; height: 100vh; background-color: #487eb0; animation-name: bgcolor, bodera, rotat; animation-duration: 2s, 2s, 3s; animation-iteration-count: 2, 2, 1; animation-direction: reverse, normal, normal; animation-fill-mode: forwards, forwards, forwards; } main::after { content: "阿顺特烦恼"; color: white; animation: opcity 2s; opacity: 0; font-size: 1.5em; animation-fill-mode: forwards; animation-delay: 4s; } @keyframes opcity { 25% { opacity: 0.2; } 50% { opacity: 0.6; } 100% { opacity: 0.8; } } @keyframes bgcolor { 25% { background-color: #fbc531; } 50% { background-color: #8c7ae6; } 75% { background-color: #f5f6fa; } 100% { background-color: #e84118; } } @keyframes bodera { 25% { border-radius: 10%; } 50% { border-radius: 25%; } 75% { border-radius: 38%; } 100% { border-radius: 50%; } } @keyframes rotat { 25% { transform: rotate(30deg); } 50% { transform: rotate(60deg); } 75% { transform: rotate(120deg); } 100% { transform: rotate(360deg); } } </style> <body> <main></main> </body>
|
关键代码解析:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| main { display: flex; justify-content: center; align-items: center; width: 100vw; height: 100vh; background-color: #487eb0; animation-name: bgcolor, bodera, rotat; animation-duration: 2s, 2s, 3s; animation-iteration-count: 2, 2, 1; animation-direction: reverse, normal, normal; animation-fill-mode: forwards, forwards, forwards; } main::after { content: "阿顺特烦恼"; color: white; animation: opcity 2s; opacity: 0; font-size: 1.5em; animation-fill-mode: forwards; animation-delay: 4s; }
|
这里为了让文字在其他动画都执行完毕后再显示,为文字动画设置了animation-delay
延迟执行,但我们要确定之前动画结束的时间,怎么计算呢?
我们知道,当应用多个动画时,它们也都是并发执行的,所以我们只要知道执行时间最长的那个动画即可。
我们需要分析这段代码:
1 2
| animation-duration: 2s, 2s, 3s; animation-iteration-count: 2, 2, 1;
|
执行次数×单次执行时间=动画总时间。因此最大时间=max(2×2 ,2×2, 3×1)=4s
因此,文字动画延迟4s。
最后
原创文章,文笔有限,才疏学浅,文中若有不正之处,速速告知。
本文到此结束,希望对你有所帮助,我是 Ashun ,在校大学生,立志成为资深前端工程师,欢迎大家一起交流、学习。后续更新更多文章,请持续关注哦~