1. 缓动效果
给过渡和动画加上缓动效果(比如具有回弹效果的过渡过程)
回弹效果是指当一个过渡达到最终值时,往回倒一点,然后再次回到最终值,如此往复一次或多次,并逐渐收敛,最终稳定在最终值。
假设要用一个元素来模拟一个下落的小球,我们会把 transform 属性从 none 过渡到 translateY(350px) 来模拟这个下落过程。
1.1 弹跳动画
CSS 提供了一个 cubic-bezier()
函数,允许我们指定自定义的调速函数。
- 它接受四个参数,分别代表两个控制锚点的坐标值,我们通过这两个控制锚点来指定想要的贝塞尔曲线。
- 语法形式是这样的:cubic-bezier(x1, y1, x2, y2),其中 (x1, y1) 表示第一个控制锚点的坐标,而 (x2, y2) 是第二个。
- 曲线片断的两个端点分别固定在(0,0) 和 (1,1),前者是整个过渡的起点(时间进度为零,动画进度为零),后者是终点(时间进度为 100%,动画进度为 100%)
<!DOCTYPE html>
<html>
<head>
<style>
@keyframes bounce {
60%, 80%, to {
transform: translateY(400px);
animation-timing-function: ease;
}
70% {
transform: translateY(300px);
}
90% {
transform: translateY(360px);
}
}
.ball {
width: 0;
height: 0;
padding: 1.5em;
border-radius: 50%;
margin: auto;
background: red radial-gradient(at 30% 30%, #fdd, red);
animation: bounce 2s cubic-bezier(0.1, 0.25, 1, 0.25) forwards;
}
body {
background: linear-gradient(skyblue, white 450px, yellowgreen 0);
min-height: 100vh;
}
</style>
</head>
<body>
<div class="ball"></div>
</body>
</html>
1.2 弹性过渡
假设有一个文本输入框,每当它被聚焦时,都需要展示一个提示框。这个提示框用来向用户提供帮助信息,比如字段值的正确格式等
CSS 属性
transform-origin
更改一个元素变形的原点。
<!DOCTYPE html>
<html>
<head>
<style>
input:not(:focus) + .callout:not(:hover) {
/*隐藏.callout*/
transform: scale(0);
transition: 0.25s transform;
}
.callout {
transition: 0.5s cubic-bezier(0.25, 0.1, 0.3, 1.5) transform;
transform-origin: 1.4em -0.4em;
}
/* Styling */
body {
padding: 1.5em;
font: 200%/1.6 Baskerville;
}
input {
display: block;
padding: 0 0.4em;
font: inherit;
}
/*提示框样式*/
.callout {
position: absolute;
max-width: 14em;
padding: 0.6em 0.8em;
border-radius: 0.3em;
margin: 0.3em 0 0 -0.2em;
background: #fed;
border: 1px solid rgba(0, 0, 0, 0.3);
box-shadow: 0.05em 0.2em 0.6em rgba(0, 0, 0, 0.2);
font-size: 75%;
}
/*三角形的箭头*/
.callout:before {
content: "";
position: absolute;
top: -0.4em;
left: 1em;
padding: 0.35em;
background: inherit;
border: inherit;
border-right: 0;
border-bottom: 0;
transform: rotate(45deg);
}
</style>
</head>
<body>
<label>
Your username:
<input value="leaverou"></input>
<span class="callout">
Only letters, numbers, underscores (_) and hyphens (-) allowed!
</span>
</label>
</body>
</html>
2. 逐帧动画
以最常见的 “加载中” 的效果为例:
使用step()函数,它可以传入一个参数,表示此次动画是分几步完成的,例如,step(8) 表示此次动画是分8部完成,也就是总共8帧,且逐帧匀速去执行的。
<!DOCTYPE html>
<html>
<head>
<style>
@keyframes loader {
to {
background-position: -800px 0;
}
}
.loader {
width: 100px;
height: 100px;
text-indent: 999px;
overflow: hidden; /* Hide text */
background: url(http://dabblet.com/img/loader.png) 0 0;
animation: loader 1s infinite steps(8);
}
</style>
</head>
<body>
<div class="loader">Loading…</div>
</body>
</html>
3. 闪烁效果
通过数次闪烁(不超过三次)来提示用户界面中有某处发生了变化。
- 比如对整个元素进行闪烁(通过 opacity 属性),
- 对文字的颜色进行闪烁(通过 color 属性),
- 对边框进行闪烁(通过 border-color 属性),等等
animation-direction
的 唯 一 作 用 就 是 反 转 每 一 个 循 环 周 期(reverse),或第偶数个循环周期(alternate),或第奇数个循环周期(alternate-reverse)。它的伟大之处在于,它会同时反转调整函数,从而产生更加逼真的动画效果
<!DOCTYPE html>
<html>
<head>
<style>
@keyframes blink-1 {
/*让状态切换发生在每个循环周期的中间*/
50% {
color: transparent;
}
}
@keyframes blink-2 {
to {
color: transparent;
}
}
p {
padding: 1em;
background: gold;
}
.blink-smooth-1 {
animation: 1s blink-1 3;
}
.blink-smooth-2 {
animation: 0.5s blink-2 6;
animation-direction: alternate;
}
.blink {
animation: 1s blink-1 3 steps(1);
}
</style>
</head>
<body>
<p class="blink-smooth-1">Peek-a-boo!</p>
<p class="blink-smooth-2">Peek-a-boo!</p>
<p class="blink">Peek-a-boo!</p>
</body>
</html>
4. 打字动画
一段文本中的字符逐个显现,模拟出一种打字的效果。
核心思路就是让容器的宽度成为动画的主体:把所有文本包裹在这个容器中,然后让它的宽度从 0 开始以步进动画的方式、一个字一个字地扩张到它应有的宽度。并不适用于多行文本
- 用 white-space:nowrap; 来阻止文本折行
- overflflow: hidden;,超出宽度的文本裁切掉
- 逐帧动画steps()所需要的步进数量是由字符的数量来决定的
- ch 单位,表示“0”字形的宽度。在等宽字体中,“0”字形的宽度和其他所有字形的宽度是一样的。
- 用右边框来模拟光标效果,infinite 关键字循环闪烁光标
<!DOCTYPE html>
<html>
<head>
<style>
@keyframes typing {
from {
width: 0;
}
}
@keyframes caret {
50% {
border-right-color: transparent;
}
}
h1 {
font: bold 200% Consolas, Monaco, monospace;
/*width: 8.25em;*/
width: 15ch;
white-space: nowrap;
overflow: hidden;
border-right: 0.05em solid;
animation: typing 8s steps(15), caret 1s steps(1) infinite;
}
</style>
</head>
<body>
<h1>CSS is awesome!</h1>
</body>
</html>
5. 状态平滑的动画——暂停动画
不是所有动画都是在页面一加载好就立即播放的。
通过动画来响应用户的动作。用户的动作会随时中断动画,而此时在默认情况下,动画只会立即停止播放,并生硬地跳回开始状态
有一个属性正好是为暂停动画的需求专门设计的:animation-play-state
<!DOCTYPE html>
<html>
<head>
<style>
@keyframes panoramic {
to {
background-position: 100% 0;
}
}
.panoramic {
width: 150px;
height: 150px;
background: url("http://c3.staticflickr.com/3/2671/3904743709_74bc76d5ac_b.jpg");
background-size: auto 100%;
animation: panoramic 10s linear infinite alternate;
animation-play-state: paused;
}
.panoramic:hover,
.panoramic:focus {
animation-play-state: running;
}
</style>
</head>
<body>
<div class="panoramic"></div>
</body>
</html>
把动画加在 .panoramic
这条样式中,但是让它一开始就处于暂停状态,直到 :hover
时再启动动画。这再也不是添加和取消动画的问题了,而只是暂停和继续一个一直存在的动画,因此再也不会有生硬的
跳回现象了
6. 沿环形路径平移的动画
用CSS 动画来让一个元素沿着环形路径动起来
我们希望它只是沿着环形进行移动,同时保持自己本来的朝向
6.1 需要两个元素的解决方案
用内层的变形来抵消外层的变形效果
- 对头像元素设置另一个旋转动画,让它以相反的方向自转一周,这两层旋转的作用会在头像上相互抵消,我们只会看到父元素旋转所产生的环绕动作
- 让内层动画从父元素那里继承所有的动画属性,然后把动画名覆盖掉
<!DOCTYPE html>
<html>
<head>
<style>
@keyframes spin {
to {
transform: rotate(1turn);
}
}
.avatar {
animation: spin 3s infinite linear;
transform-origin: 50% 150px;
}
.avatar > img {
animation: inherit;
animation-direction: reverse;
/*reverse 值,可以得到原始动画的反向版本*/
}
/* Anything below this is just styling */
.avatar {
width: 50px;
margin: 0 auto;
border-radius: 50%;
overflow: hidden;
}
.avatar > img {
display: block;
width: inherit;
}
.path {
width: 300px;
height: 300px;
padding: 20px;
border-radius: 50%;
background: #fb3;
}
</style>
</head>
<body>
<div class="path">
<div class="avatar">
<img src="http://lea.verou.me/book/adamcatlace.jpg" />
</div>
</div>
</body>
</html>
6.2 单个元素的解决方案
用两次位移变形(translate)来代替变形原点(transform-origin)的作用
每个
transform-origin
都是可以被两个translate()
模拟出来的
transform: rotate(30deg);
transform-origin: 200px 300px;
/*等价*/
transform: translate(200px, 300px) rotate(30deg) translate(-200px, -300px);
transform-origin: 0 0;
每个变形函数并不是只对这个元素进行变形,而且会把整个元素的坐标系统进行变形,从而影响所有后续的变形操作。
可以把两套动画合并为一套,并只用在 .avatar这一个元素上
把头像放在圆心并以此作为起点,我们就可以消除最开始的那两个位移操作了
<!DOCTYPE html>
<html>
<head>
<style>
@keyframes spin {
from {
transform: rotate(0turn) translateY(-150px) translateY(50%)
rotate(1turn);
}
to {
transform: rotate(1turn) translateY(-150px) translateY(50%)
rotate(0turn);
}
}
.avatar {
animation: spin 3s infinite linear;
}
/* Anything below this is just styling */
.avatar {
display: block;
width: 50px;
margin: calc(50% - 25px) auto 0;
border-radius: 50%;
overflow: hidden;
}
.path {
width: 300px;
height: 300px;
padding: 20px;
margin: 100px auto;
border-radius: 50%;
background: #fb3;
}
</style>
</head>
<body>
<div class="path">
<img src="http://lea.verou.me/book/adamcatlace.jpg" class="avatar" />
</div>
</body>
</html>
暂无评论内容