CSS 动画可以在不借助 Javascript 的情况下做出一些简单的动画效果。
你也可以通过 Javascript 控制 CSS 动画,使用少量的代码,就能让动画表现更加出色。
CSS 过渡(transition)[#css-transition]
CSS 过渡的理念非常简单,我们只需要定义某一个属性以及如何动态地表现其变化。当属性变化时,浏览器将会绘制出相应的过渡动画。
也就是说:我们只需要改变某个属性,然后所有流畅的动画都由浏览器生成。
举个例子,以下 CSS 会为 backgroud-color 的变化生成一个 3 秒的过渡动画:
.animated {
transition-property: background-color;
transition-duration: 3s;
}
现在,只要一个元素拥有名为 .animated 的类,那么任何背景颜色的变化都会被渲染为 3 秒钟的动画。
单击以下按钮以演示动画:
<button id="color">Click me</button>
<style>
#color {
transition-property: background-color;
transition-duration: 3s;
}
</style>
<script>
color.onclick = function() {
this.style.backgroundColor = 'red';
};
</script>
CSS 提供了四个属性来描述一个过渡:
transition-propertytransition-durationtransition-timing-functiontransition-delay
之后我们会详细介绍它们,目前我们需要知道,我们可以在 transition 中以 property duration timing-function delay 的顺序一次性定义它们,并且可以同时为多个属性设置过渡动画。
请看以下例子,点击按钮生成 color 和 font-size 的过渡动画:
<button id="growing">Click me</button>
<style>
#growing {
transition: font-size 3s, color 2s;
}
</style>
<script>
growing.onclick = function() {
this.style.fontSize = '36px';
this.style.color = 'red';
};
</script>
现在让我们一个一个展开看这些属性。
transition-property
在 transition-property 中我们可以列举要设置动画的所有属性,如:left、margin-left、height 和 color。
不是所有的 CSS 属性都可以使用过渡动画,但是它们中的大多数都是可以的。all 表示应用在所有属性上。
transition-duration
transition-duration 允许我们指定动画持续的时间。时间的格式参照 CSS 时间格式:单位为秒 s 或者毫秒 ms。
transition-delay
transition-delay 允许我们设定动画开始前的延迟时间。例如,对于 transition-delay: 1s,动画将会在属性变化发生 1 秒后开始渲染。
你也可以提供一个负值。那么动画将会从整个过渡的中间时刻开始渲染。例如,对于 transition-duration: 2s,同时把 delay 设置为 -1s,那么这个动画将会持续 1 秒钟,并且从正中间开始渲染。
这里演示了数字从 0 到 9 的动画,使用了 CSS translate 方法:
stripe.onclick = function() {
stripe.classList.add('animate');
};#digit {
width: .5em;
overflow: hidden;
font: 32px monospace;
cursor: pointer;
}
#stripe {
display: inline-block
}
#stripe.animate {
transform: translate(-90%);
transition-property: transform;
transition-duration: 9s;
transition-timing-function: linear;
}<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">
</head>
<body>
Click below to animate:
<div id="digit"><div id="stripe">0123456789</div></div>
<script src="script.js"></script>
</body>
</html>如下在 tranform 属性上应用动画:
#stripe.animate {
transform: translate(-90%);
transition-property: transform;
transition-duration: 9s;
}
在以上的例子中,JavaScript 把 .animate 类添加到了元素上,由此触发了动画:
stripe.classList.add('animate');
我们也可以『从中间』开始,也就是说从某个特定数字开始,比方说,从当前的时间的秒数开始。这就要用到负的 transition-delay。
此处,如果你单击这个数字,那么它会从当前的秒数开始渲染:
stripe.onclick = function() {
let sec = new Date().getSeconds() % 10;
stripe.style.transitionDelay = '-' + sec + 's';
stripe.classList.add('animate');
};#digit {
width: .5em;
overflow: hidden;
font: 32px monospace;
cursor: pointer;
}
#stripe {
display: inline-block
}
#stripe.animate {
transform: translate(-90%);
transition-property: transform;
transition-duration: 9s;
transition-timing-function: linear;
}<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">
</head>
<body>
Click below to animate:
<div id="digit"><div id="stripe">0123456789</div></div>
<script src="script.js"></script>
</body>
</html>只需添加一行 JavaScript 代码:
stripe.onclick = function() {
let sec = new Date().getSeconds() % 10;
// for instance, -3s here starts the animation from the 3rd second
stripe.style.transitionDelay = '-' + sec + 's';
stripe.classList.add('animate');
};
transition-timing-function
时间函数描述了动画进程在时间上的分布。它是先慢后快还是先快后慢?
乍一看,这可能是最复杂的属性了,但是稍微花点时间,你就会发现其实也很简单。
这个属性接受两种值:一个贝塞尔曲线(Bezier curve)或者阶跃函数(steps)。我们先从贝塞尔曲线开始,这也是较为常用的。
贝塞尔曲线(Bezier curve)
时间函数可以用贝塞尔曲线描述,通过设置四个满足以下条件的控制点:
- 第一个应为:
(0,0)。 - 最后一个应为:
(1,1)。 - 对于中间值,
x必须位于0..1之间,y可以为任意值。
CSS 中设置一贝塞尔曲线的语法为:cubic-bezier(x2, y2, x3, y3)。这里我们只需要设置第二个和第三个值,因为第一个点固定为 (0,0),第四个点固定为 (1,1)。
时间函数描述了动画进行的快慢。
x轴表示时间:0—— 开始时刻,1——transition-duration的结束时刻。y轴表示过程的完成度:0—— 属性的起始值,1—— 属性的最终值。
最简单的一种情况就是动画匀速进行,可以通过设置曲线为 cubic-bezier(0, 0, 1, 1) 来实现。
看上去就像这样:
…正如我们所见,这就是条直线。随着时间 x 推移,完成度 y 稳步从 0 增长到 1。
例子中的列车匀速地从左侧移动到右侧:
.train {
position: relative;
cursor: pointer;
width: 177px;
height: 160px;
left: 0;
transition: left 5s cubic-bezier(0, 0, 1, 1);
}<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">
</head>
<body>
<img class="train" src="https://js.cx/clipart/train.gif" onclick="this.style.left='450px'">
</body>
</html>这个里面的 CSS 就是基于刚才那条曲线的:
.train {
left: 0;
transition: left 5s cubic-bezier(0, 0, 1, 1);
/* JavaScript sets left to 450px */
}
…那么,我们如果表现出减速行驶的列车呢?
我们可以使用另一条贝塞尔曲线:cubic-bezier(0.0, 0.5, 0.5 ,1.0)。
图像如下:
正如我们所见,这个过程起初很快:曲线开始迅速升高,然后越来越慢。
这是实际的效果演示:
.train {
position: relative;
cursor: pointer;
width: 177px;
height: 160px;
left: 0px;
transition: left 5s cubic-bezier(0.0, 0.5, 0.5, 1.0);
}<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">
</head>
<body>
<img class="train" src="https://js.cx/clipart/train.gif" onclick="this.style.left='450px'">
</body>
</html>CSS:
.train {
left: 0;
transition: left 5s cubic-bezier(0, .5, .5, 1);
/* JavaScript sets left to 450px */
}
CSS 提供几条内建的曲线:linear、ease、ease-in、ease-out 和 ease-in-out。
linear 其实就是 cubic-bezier(0, 0, 1, 1) 的简写 —— 一条直线,刚刚我们已经看过了。
其它的名称是以下贝塞尔曲线的简写:
ease* |
ease-in |
ease-out |
|
|---|