过渡、动画和变换
1、使用过渡
过渡效果一般是由浏览器直接改变元素的 CSS 属性实现的。例如,如果使用 :hover 选择器,一旦用户将鼠标悬停在元素上,浏览器就会跟选择器关联的属性。
<!DOCTYPE HTML>
<html>
<head>
<title>Example</title>
<meta name="author" content="Adam Freeman"/>
<meta name="description" content="A simple example"/>
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
<style>
p {
padding: 5px;
border: medium double black;
background-color: lightgrey;
font-family: sans-serif;
}
#banana {
font-size: large;
border: medium solid black;
}
#banana:hover {
font-size: x-large;
border: medium solid white;
background-color: green;
color: white;
padding: 4px;
}
</style>
</head>
<body>
<p>
There are lots of different kinds of fruit - there are over 500
varieties of <span id="banana">banana</span> alone. By the time we add the
countless types of apples, oranges, and other
well-known fruit, we are faced with thousands of choices.
</p>
</body>
</html>
例子中,为一个 span 元素定义了两种样式。一种通用样式(选择器 #banana),一种样式只有在用户将鼠标悬停到元素上的时候才应用(#banana:hover 选择器)。
CSS 过渡特性允许我们控制应用到新属性值的速度。比如你可以选择逐渐改变示例中的 span 元素的外观,让鼠标移到单词 banana 上的效果更和谐。
属性 | 说明 | 值 |
---|---|---|
transaction-delay | 指定过渡开始之前的延迟时间 | <时间> |
transaction-duration | 指定过渡的持续时间 | <时间> |
transaction-property | 指定应用过渡的属性 | <字符串> |
transaction-timing-function | 指定过渡期间计算中间值的方式 | 参照下表 |
transaction | 在一条声明中指定所有过渡细节的简写属性 | 参照下表 |
transaction 简写属性的格式如下:
transaction: <transaction-property> <transaction-duration> <transaction-timing-function> <transaction-delay>
<!DOCTYPE HTML>
<html>
<head>
<title>Example</title>
<meta name="author" content="Adam Freeman"/>
<meta name="description" content="A simple example"/>
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
<style>
p {
padding: 5px;
border: medium double black;
background-color: lightgrey;
font-family: sans-serif;
}
#banana {
font-size: large;
border: medium solid black;
}
#banana:hover {
font-size: x-large;
border: medium solid white;
background-color: green;
color: white;
padding: 4px;
-webkit-transition-delay: 100ms;
-webkit-transition-property: background-color, color, padding,
font-size, border;
-webkit-transition-duration: 500ms;
}
</style>
</head>
<body>
<p>
There are lots of different kinds of fruit - there are over 500
varieties of <span id="banana">banana</span> alone. By the time we add the
countless types of apples, oranges, and other
well-known fruit, we are faced with thousands of choices.
</p>
</body>
</html>
1.1、创建反向过渡
过渡只有在应用于其关联的样式时才会生效。示例样式中使用了 :hover 选择器,这意味着只有用户将鼠标悬停在 span 元素上才会应用样式。用户一旦将鼠标从 span 元素上移开,只剩下 #banana 样式,默认情况下,元素的外观会立刻回到初始状态。
因为这个原因,大多数过渡成对出现:暂时状态的过渡和方向相反的反向过渡。下面代码展示了如何通过应用另一种过渡样式平滑地返回初始样式。
<!DOCTYPE HTML>
<html>
<head>
<title>Example</title>
<meta name="author" content="Adam Freeman"/>
<meta name="description" content="A simple example"/>
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
<style>
p {
padding: 5px;
border: medium double black;
background-color: lightgrey;
font-family: sans-serif;
}
#banana {
font-size: large;
border: medium solid black;
-webkit-transition-delay: 10ms;
-webkit-transition-duration: 250ms;
}
#banana:hover {
font-size: x-large;
border: medium solid white;
background-color: green;
color: white;
padding: 4px;
-webkit-transition-delay: 100ms;
-webkit-transition-property: background-color, color, padding,
font-size, border;
-webkit-transition-duration: 500ms;
}
</style>
</head>
<body>
<p>
There are lots of different kinds of fruit - there are over 500
varieties of <span id="banana">banana</span> alone. By the time we add the
countless types of apples, oranges, and other
well-known fruit, we are faced with thousands of choices.
</p>
</body>
</html>
省略了 transaction-property 属性,这样所有的属性都会在整个持续时间内逐渐应用过渡。还指定了初始 10ms 的延迟,以及 250ms 的持续时间。添加一个反向过渡后,返回初始状态看上去就没那么突兀了。
1.2、选择中间值的计算方式
使用过渡时,浏览器需要为每个属性计算初始值和最终值之间的中间值。使用 transaction-timing-function 属性指定计算中间值的方式,表示为四个点控制的三次贝塞尔曲线。有五种预设曲线可以选择:
- ease(默认值)
- linear
- ease-in
- ease-out
- ease-in-out
<!DOCTYPE HTML>
<html>
<head>
<title>Example</title>
<meta name="author" content="Adam Freeman"/>
<meta name="description" content="A simple example"/>
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
<style>
p {
padding: 5px;
border: medium double black;
background-color: lightgrey;
font-family: sans-serif;
}
#banana {
font-size: large;
border: medium solid black;
-webkit-transition-delay: 10ms;
-webkit-transition-duration: 250ms;
}
#banana:hover {
font-size: x-large;
border: medium solid white;
background-color: green;
color: white;
padding: 4px;
-webkit-transition-delay: 100ms;
-webkit-transition-property: background-color, color, padding,
font-size, border;
-webkit-transition-duration: 500ms;
-webkit-transition-timing-function: linear;
}
</style>
</head>
<body>
<p>
There are lots of different kinds of fruit - there are over 500
varieties of <span id="banana">banana</span> alone. By the time we add the
countless types of apples, oranges, and other
well-known fruit, we are faced with thousands of choices.
</p>
</body>
</html>
2、使用动画
属性 | 说明 | 值 |
---|---|---|
animation-delay | 设置动画开始前的延迟 | <时间> |
animation-direction | 设置动画循环播放的时候能否反向播放 | normal alternate |
animation-duration | 设置动画播放的持续时间 | <时间> |
animation-iteration-count | 设置动画的播放次数 | infinite <数值> |
animation-name | 指定动画名称 | none <字符串> |
animation-play-state | 允许动画暂停和重新播放 | running paused |
animation-timing-function | 指定如何计算中间动画值 | ease linear ease-in ease-out ease-in-out ease-bezier |
animation | 简写属性 |
animation 简写属性的格式如下:
animation: <animation-name> <animation-duration> <animation-timing-function> <animation-delay> <animation-iteration-count>
这些属性都不是指定要作为动画的 CSS 属性的。这是因为动画是在两部分定义的。第一部分包含在样式声明中,使用上表列出的属性。它们定义了动画的样式,但并没有定义哪些属性是动画。第二部分使用 @key-frames 规则创建,用来定义应用动画的属性。
<!DOCTYPE HTML>
<html>
<head>
<title>Example</title>
<meta name="author" content="Adam Freeman"/>
<meta name="description" content="A simple example"/>
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
<style>
p {
padding: 5px;
border: medium double black;
background-color: lightgrey;
font-family: sans-serif;
}
#banana {
font-size: large;
border: medium solid black;
}
#banana:hover {
-webkit-animation-delay: 100ms;
-webkit-animation-duration: 500ms;
-webkit-animation-iteration-count: infinite;
-webkit-animation-timing-function: linear;
-webkit-animation-name: 'GrowShrink';
}
@-webkit-keyframes GrowShrink {
to {
font-size: x-large;
border: medium solid white;
background-color: green;
color: white;
padding: 4px;
}
}
</style>
</head>
<body>
<p>
There are lots of different kinds of fruit - there are over 500
varieties of <span id="banana">banana</span> alone. By the time we add the
countless types of apples, oranges, and other
well-known fruit, we are faced with thousands of choices.
</p>
</body>
</html>
第一部分是在样式中定义动画属性,是跟 #banana:hover 选择器一起的。我们先看看基本属性:选择器样式应用 100ms 后开始播放动画,持续时间 500ms,无限重复播放,中间值使用 linear 函数计算。除了重复播放动画,这些属性在过渡中都有对应属性。
这些基本的属性并没有指出为哪些 CSS 属性应用动画。为此,要使用 animation-name 属性给动画起个名字,这里叫 GrowShrink。这样,就相当于告诉浏览器找一组名为 GrowShrink 的关键帧,然后将这些基本属性的值应用到 @keyframes 指定的动画属性上。下面是关键帧的声明:
@-webkit-keyframes GrowShrink {
to {
font-size: x-large;
border: medium solid white;
background-color: green;
color: white;
padding: 4px;
}
}
声明是开始是 @keyframes,接着指定了这组关键帧的名字 GrowShrink。声明内部指定了一组要应用动画效果的属性。这里的一个 to 声明中指定了五个属性及其值。这是关键帧设置最简单的类型。to 声明定义了一组设置动画样式的属性,同时也定义了动画结束时这些属性的最终值。动画的初始值来自进行动画处理的元素在应用样式之前的属性值。
2.1、使用关键帧
2.1.1、设置初始状态
在前面的代码中,要处理为动画的属性的初始值来自元素自身,你可以使用 from 子句指定另一组初始值。
<style>
p {
padding: 5px;
border: medium double black;
background-color: lightgrey;
font-family: sans-serif;
}
#banana {
font-size: large;
border: medium solid black;
}
#banana:hover {
-webkit-animation-delay: 100ms;
-webkit-animation-duration: 500ms;
-webkit-animation-iteration-count: infinite;
-webkit-animation-timing-function: linear;
-webkit-animation-name: 'GrowShrink';
}
@-webkit-keyframes GrowShrink {
from{
from-size:x-large;
background-color: red;
}
to {
font-size: x-large;
border: medium solid white;
background-color: green;
color: white;
padding: 4px;
}
}
</style>
2.1.2、指定中间关键帧
也可以添加其他关键帧定义动画的中间阶段,这是通过添加百分数子句实现的。
<style>
p {
padding: 5px;
border: medium double black;
background-color: lightgrey;
font-family: sans-serif;
}
#banana {
font-size: large;
border: medium solid black;
}
#banana:hover {
-webkit-animation-delay: 100ms;
-webkit-animation-duration: 500ms;
-webkit-animation-iteration-count: infinite;
-webkit-animation-timing-function: linear;
-webkit-animation-name: 'GrowShrink';
}
@-webkit-keyframes GrowShrink {
from{
from-size:x-large;
background-color: red;
}
50%{
background-color: yellow;
padding: 1px;
}
75%{
color: white;
padding: 2px;
}
to {
font-size: x-large;
border: medium solid white;
background-color: green;
color: white;
padding: 4px;
}
}
</style>
中间关键帧有两个用途。一是为属性定义新的变化速率。padding 属性的设置就是从这个角度出发的。在中间点(由 50% 子句定义),动画元素的内边距是 1px;在 75% 处,内边距是 2px;而在动画结束的时候,内边距被设置为 4px。浏览器会使用 animation-timing-function 属性指定的调速函数计算由一个关键帧移动到下一个关键帧需要的中间值,以确保关键帧与关键帧之间流畅地播放。
中间关键帧的另一个用途是定义属性值,以便创建更为复杂的动画。background-color 属性的设置就是从和这个角度出发。初始值(red)在 from 子句中定义,在 50% 处,这个值会变成 yellow,而在动画结束时,它又变成 green。通过添加非序列化的中间值,在一个动画中创建了两个颜色过渡:由红色到黄色,由黄色到绿色。
2.2、设置重复方向
动画结束后浏览器可以选择接下来动画以何种方式重复。使用 animation-direction 属性指定首选方式。
值 | 说明 |
---|---|
normal | 每次重复都向前播放,如果可重复播放多次,每次动画都恢复初始状态,从头开始播放 |
alternate | 动画先向前播放,然后反方向播放,相当于 animation-iteration-count 属性设置为 2 |
<style>
p {
padding: 5px;
border: medium double black;
background-color: lightgrey;
font-family: sans-serif;
}
#banana {
font-size: large;
border: medium solid black;
}
#banana:hover {
-webkit-animation-delay: 100ms;
-webkit-animation-duration: 500ms;
-webkit-animation-iteration-count: 2;
-webkit-animation-iteration-count: infinite;
-webkit-animation-timing-function: linear;
-webkit-animation-name: 'GrowShrink';
-webkit-animation-direction: alternate;
}
@-webkit-keyframes GrowShrink {
to {
font-size: x-large;
border: medium solid white;
background-color: green;
color: white;
padding: 4px;
}
}
</style>
这个例子中,使用了 animation-iteration-count 属性指定动画重复播放的次数。第二次迭代结束后,动画元素就回到初始状态。我为 animation-direction 属性使用了 alternate 值,动画就会首先向前播放,之后反方向播放。
如果将 animation-iteration-count 属性的值设为 infinite,那么只要鼠标悬停在 span 元素上,动画就无休止地向前和向后交替播放。
normal 值则会让动画回到初始状态,每次重复播放都是向前播放。
2.3、理解结束状态
CSS 动画的一个局限是关键帧为属性定义的值只能在动画中应用。动画结束后,动画元素的外观回到初始状态。
<style>
p {
padding: 5px;
border: medium double black;
background-color: lightgrey;
font-family: sans-serif;
}
#banana {
font-size: large;
border: medium solid black;
}
#banana:hover {
-webkit-animation-delay: 100ms;
-webkit-animation-duration: 500ms;
-webkit-animation-iteration-count: 1;
-webkit-animation-timing-function: linear;
-webkit-animation-name: 'GrowShrink';
}
@-webkit-keyframes GrowShrink {
to {
font-size: x-large;
border: medium solid white;
background-color: green;
color: white;
padding: 4px;
}
}
</style>
这段代码制造的效果就是即使鼠标仍然悬停在 span 元素上,元素的外观在动画结束后回到了初始状态——动画状态完全消失。
2.4、初始布局时应用动画
跟过渡相比,动画的一个优势是你可以将其应用到页面的初始布局。
<style>
p {
padding: 5px;
border: medium double black;
background-color: lightgrey;
font-family: sans-serif;
}
#banana {
font-size: large;
border: medium solid black;
}
#banana {
font-size: large;
border: medium solid black;
-webkit-animation-duration: 2500ms;
-webkit-animation-iteration-count: infinite;
-webkit-animation-timing-function: linear;
-webkit-animation-name: 'ColorSwap';
-webkit-animation-direction: alternate;
}
@-webkit-keyframes ColorSwap {
to {
border: medium solid white;
background-color: green;
}
}
</style>
这个例子中,在样式 #banana 选择器中定义了动画。页面一旦加载就会自动应用样式,这就意味着浏览器一旦显示 HTML 就有了动画效果。
2.5、重用关键帧
我们可以对同一组关键帧应用多个动画,从而为动画属性配置不同的值。
<!DOCTYPE HTML>
<html>
<head>
<title>Example</title>
<meta name="author" content="Adam Freeman"/>
<meta name="description" content="A simple example"/>
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
<style>
p {
padding: 5px;
border: medium double black;
background-color: lightgrey;
font-family: sans-serif;
}
span {
font-size: large;
border: medium solid black;
}
#banana {
-webkit-animation-duration: 2500ms;
-webkit-animation-iteration-count: infinite;
-webkit-animation-direction: alternate;
-webkit-animation-timing-function: linear;
-webkit-animation-name: 'ColorSwap';
}
#apple {
-webkit-animation-duration: 500ms;
-webkit-animation-iteration-count: infinite;
-webkit-animation-direction: normal;
-webkit-animation-timing-function: ease-in-out;
-webkit-animation-name: 'ColorSwap';
}
@-webkit-keyframes ColorSwap {
to {
border: medium solid white;
background-color: green;
}
}
</style>
</head>
<body>
<p>
There are lots of different kinds of fruit - there are over 500
varieties of <span id="banana">banana</span> alone. By the time we add the
countless types of <span id="apple">apples</span>, oranges, and other
well-known fruit, we are faced with thousands of choices.
</p>
</body>
</html>
两个样式,它们都使用了 ColorSwap 关键帧。跟 #apple 选择器关联的动画弧执行一小段时间,且跟 #banana 选择器关联的动画使用的计时函数不同,不过两者都是向前播放。
2.6、为多个元素应用多个动画
前面例子的一个变体是为多个元素应用同一个动画。在包含动画细节的样式中,扩展选择器的范围即可实现这一点。
<style>
p {
padding: 5px;
border: medium double black;
background-color: lightgrey;
font-family: sans-serif;
}
span {
font-size: large;
border: medium solid black;
}
#banana, #apple {
-webkit-animation-duration: 2500ms;
-webkit-animation-iteration-count: infinite;
-webkit-animation-direction: alternate;
-webkit-animation-timing-function: linear;
-webkit-animation-name: 'ColorSwap';
}
@-webkit-keyframes ColorSwap {
to {
border: medium solid white;
background-color: green;
}
}
</style>
还可以为一个元素应用多个动画,只需要用逗号将动画属性的不同值隔开即可。
<style>
p {
padding: 5px;
border: medium double black;
background-color: lightgrey;
font-family: sans-serif;
}
span {
font-size: large;
border: medium solid black;
}
#banana, #apple {
-webkit-animation-duration: 2500ms;
-webkit-animation-iteration-count: infinite;
-webkit-animation-direction: alternate;
-webkit-animation-timing-function: linear;
-webkit-animation-name: 'ColorSwap', 'GrowShrink';
}
@-webkit-keyframes ColorSwap {
to {
border: medium solid white;
background-color: green;
}
}
@-webkit-keyframes GrowShrink {
to {
font-size: x-large;
border: medium solid white;
background-color: green;
color: white;
padding: 4px;
}
}
</style>
2.7、停止和启动动画
animation-play-state 属性可以用来停止和启动动画。如果这个属性的值为 paused,动画就会停止。如果换成 playing,动画就会开始播放。
<!DOCTYPE HTML>
<html>
<head>
<title>Example</title>
<meta name="author" content="Adam Freeman"/>
<meta name="description" content="A simple example"/>
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
<style>
#fruittext {
padding: 5px;
border: medium double black;
background-color: lightgrey;
font-family: sans-serif;
}
#banana {
-webkit-animation-duration: 2500ms;
-webkit-animation-iteration-count: infinite;
-webkit-animation-direction: alternate;
-webkit-animation-timing-function: linear;
-webkit-animation-name: 'GrowShrink';
}
@-webkit-keyframes GrowShrink {
from {
font-size: large;
border: medium solid black;
}
to {
font-size: x-large;
border: medium solid white;
background-color: green;
color: white;
padding: 4px;
}
}
</style>
</head>
<body>
<p id="fruittext">
There are lots of different kinds of fruit - there are over 500
varieties of <span id="banana">banana</span> alone. By the time we add the
countless types of apples, oranges, and other
well-known fruit, we are faced with thousands of choices.
</p>
<p>
<button>Running</button>
<button>Paused</button>
</p>
<script>
var buttons = document.getElementsByTagName("BUTTON");
for (var i = 0; i < buttons.length; i++) {
buttons[i].onclick = function(e) {
document.getElementById("banana").style.webkitAnimationPlayState =
e.target.innerHTML;
};
}
</script>
</body>
</html>
3、使用变换
可以使用 CSS 变换为元素应用线性变换,也就是说你可以旋转、缩放、倾斜和平移某个元素。
属性 | 说明 | 值 |
---|---|---|
transform | 指定应用的变换功能 | 参照下表 |
transform-origin | 指定变换的起点 | 参照下表 |
3.1、应用变换
通过 transform 属性为元素应用变换。这个属性允许的值是一组预定义的函数。
值 | 说明 |
---|---|
translate(<长度值或百分数值>) translateX(<长度值或百分数值>) translateY(<长度值或百分数值>) | 在水平方向、垂直方向或者两个方向上平移元素 |
scale(<数值>) scaleX(<数值>) scaleY(<数值>) | 在水平方向、垂直方向或者两个方向上缩放元素 |
rotate(<角度>) | 旋转元素 |
skew(<角度>) skewX(<角度>) skewY(<角度>) | 在水平方向、垂直方向或者两个方向上使元素倾斜一定角度 |
matrix(4~6 个数值,逗号隔开) | 指定自定义变换。 |
<!DOCTYPE HTML>
<html>
<head>
<title>Example</title>
<meta name="author" content="Adam Freeman"/>
<meta name="description" content="A simple example"/>
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
<style>
p {
padding: 5px;
border: medium double black;
background-color: lightgrey;
font-family: sans-serif;
}
#banana {
font-size: x-large;
border: medium solid white;
background-color: green;
color: white;
padding: 4px;
-moz-transform: rotate(-45deg) scaleX(1.2);
}
</style>
</head>
<body>
<p id="fruittext">
There are lots of different kinds of fruit - there are over 500
varieties of <span id="banana">banana</span> alone. By the time we add the
countless types of apples, oranges, and other
well-known fruit, we are faced with thousands of choices.
</p>
</body>
</html>
3.2、指定元素变换的起点
transform-origin 属性允许我们指定应用变换的起点。默认情况下,使用元素的中心作为起点。
值 | 说明 |
---|---|
<%> | 指定元素 x 轴或者 y 轴的起点 |
<长度值> | 指定距离 |
left center Right | 指定 x 轴上的位置 |
top center bottom | 指定 y 轴上的位置 |
<!DOCTYPE HTML>
<html>
<head>
<title>Example</title>
<meta name="author" content="Adam Freeman"/>
<meta name="description" content="A simple example"/>
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
<style>
p {
padding: 5px;
border: medium double black;
background-color: lightgrey;
font-family: sans-serif;
}
#banana {
font-size: x-large;
border: medium solid white;
background-color: green;
color: white;
padding: 4px;
-moz-transform: rotate(-45deg) scaleX(1.2);
-moz-transform-origin: right top;
}
</style>
</head>
<body>
<p id="fruittext">
There are lots of different kinds of fruit - there are over 500
varieties of <span id="banana">banana</span> alone. By the time we add the
countless types of apples, oranges, and other
well-known fruit, we are faced with thousands of choices.
</p>
</body>
</html>
3.3、将变换作为动画和过渡处理
<!DOCTYPE HTML>
<html>
<head>
<title>Example</title>
<meta name="author" content="Adam Freeman"/>
<meta name="description" content="A simple example"/>
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
<style>
p {
padding: 5px;
border: medium double black;
background-color: lightgrey;
font-family: sans-serif;
}
#banana {
font-size: x-large;
border: medium solid white;
background-color: green;
color: white;
padding: 4px;
}
#banana:hover {
-moz-transition-duration: 1.5s;
-moz-transform: rotate(360deg);
}
</style>
</head>
<body>
<p id="fruittext">
There are lots of different kinds of fruit - there are over 500
varieties of <span id="banana">banana</span> alone. By the time we add the
countless types of apples, oranges, and other
well-known fruit, we are faced with thousands of choices.
</p>
</body>
</html>