aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/web/css/css_animations/using_css_animations/index.html
blob: 59dc8370eadcdccfef2a316e4cc316141cc1a3e3 (plain)
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
---
title: 使用 CSS 动画
slug: Web/CSS/CSS_Animations/Using_CSS_animations
tags:
  - Advanced
  - CSS
  - CSS Animations
  - Example
  - Experimental
  - Guide
  - Using CSS animations
translation_of: Web/CSS/CSS_Animations/Using_CSS_animations
---
<p>{{SeeCompatTable}}{{CSSRef}}</p>

<p><strong>CSS animations </strong>使得可以将从一个CSS样式配置转换到另一个CSS样式配置。动画包括两个部分:描述动画的样式规则和用于指定动画开始、结束以及中间点样式的关键帧。</p>

<p>相较于传统的脚本实现动画技术,使用CSS动画有三个主要优点:</p>

<ol>
 <li><span style="line-height: 1.5;">能够非常容易地创建简单动画,你甚至不需要了解JavaScript就能创建动画。</span></li>
 <li><span style="line-height: 1.5;">动画运行效果良好,甚至在低性能的系统上。渲染引擎会使用跳帧或者其他技术以保证动画表现尽可能的流畅。而使用JavaScript实现的动画通常表现不佳(除非经过很好的设计)。</span></li>
 <li style="margin-bottom: 0px;"><span style="line-height: 1.5;">让浏览器控制动画序列,允许浏览器优化性能和效果,如降低位于隐藏选项卡中的动画更新频率。</span></li>
</ol>

<h2 id="配置动画">配置动画</h2>

<p>创建动画序列,需要使用{{ cssxref("animation") }}属性或其子属性,该属性允许配置动画时间、时长以及其他动画细节,但该属性不能配置动画的实际表现,动画的实际表现是由 {{ cssxref("@keyframes") }}规则实现,具体情况参见<a href="#使用keyframes定义动画序列">使用keyframes定义动画序列</a>小节部分。</p>

<p style="margin-bottom: 0px;"><span style="line-height: 1.5;">{{ cssxref("animation") }}</span>的子属性有:</p>

<p style="margin-bottom: 0px;"> </p>

<dl>
 <dt><strong style="font-weight: bold;">{{ cssxref("animation-delay") }}</strong></dt>
 <dd>设置延时,即从元素加载完成之后到动画序列开始执行的这段时间。</dd>
 <dt><strong style="font-weight: bold;">{{ cssxref("animation-direction") }}</strong></dt>
 <dd>设置动画在每次运行完后是反向运行还是重新回到开始位置重复运行。</dd>
 <dt><strong style="font-weight: bold;">{{ cssxref("animation-duration") }}</strong></dt>
 <dd>设置动画一个周期的时长。</dd>
 <dt><strong style="font-weight: bold;">{{ cssxref("animation-iteration-count") }}</strong></dt>
 <dd>设置动画重复次数, 可以指定infinite无限次重复动画</dd>
 <dt><strong style="font-weight: bold;">{{ cssxref("animation-name") }}</strong></dt>
 <dd><span style="line-height: 1.5;">指定由</span>{{ cssxref("@keyframes") }}<span style="line-height: 1.5;">描述的关键帧名称。</span></dd>
 <dt><strong style="font-weight: bold;">{{ cssxref("animation-play-state") }}</strong></dt>
 <dd>允许暂停和恢复动画。</dd>
 <dt><strong style="font-weight: bold;">{{ cssxref("animation-timing-function") }}</strong></dt>
 <dd>设置动画速度, 即通过建立加速度曲线,设置动画在关键帧之间是如何变化。</dd>
 <dt><strong style="font-weight: bold;">{{ cssxref("animation-fill-mode") }}</strong></dt>
 <dd>指定动画执行前后如何为目标元素应用样式。</dd>
</dl>

<p style="margin-bottom: 0px;"> </p>

<h2 id="使用keyframes定义动画序列">使用keyframes定义动画序列</h2>

<p style="margin-bottom: 0px;">一旦完成动画的时间设置, 接下来就需要定义动画的表现。通过使用{{ cssxref("@keyframes") }}建立两个或两个以上关键帧来实现。每一个关键帧都描述了动画元素在给定的时间点上应该如何渲染。</p>

<p style="margin-bottom: 0px;"> </p>

<p style="margin-bottom: 0px;">因为动画的时间设置是通过CSS样式定义的,关键帧使用{{ cssxref("percentage") }}来指定动画发生的时间点。<code>0%</code>表示动画的第一时刻,<code>100%</code>表示动画的最终时刻。因为这两个时间点十分重要,所以还有特殊的别名:<code>from</code><code>to</code>。这两个都是可选的,若<code>from/0%</code><code>to/100%</code>未指定,则浏览器使用计算值开始或结束动画。</p>

<p style="margin-bottom: 0px;"> </p>

<p style="margin-bottom: 0px;">也可包含额外可选的关键帧,描述动画开始和结束之间的状态。</p>

<p style="margin-bottom: 0px;"> </p>

<h2 id="示例">示例</h2>

<div class="note"><strong>注意:</strong> <span style="color: #4d4e53; font-style: normal; line-height: 1.5;">这里的示例没有在CSS动画属性上使用任何前缀,Webkit内核浏览器或者早期版本浏览器可能需要前缀,下面的实例包含了<code>-webkit-</code>前缀。</span></div>

<h3 id="文本滑过浏览器窗口">文本滑过浏览器窗口</h3>

<p><span style="line-height: 1.5;">该例中{{ HTMLElement("p") }} </span><span style="line-height: 1.5;">元素由浏览器窗口右边滑至左边</span></p>

<pre class="brush: css">p {
  animation-duration: 3s;
  animation-name: slidein;
}

@keyframes slidein {
  from {
    margin-left: 100%;
    width: 300%;
  }

  to {
    margin-left: 0%;
    width: 100%;
  }
}
</pre>

<p style="margin-bottom: 0px;">{{ cssxref("animation-duration") }}属性指定 {{ HTMLElement("p") }} 上的动画从开始到结束耗费3秒,{{ cssxref("@keyframes") }} 指定使用名字为"slidein"的关键帧。</p>

<p style="margin-bottom: 0px;"> </p>

<p style="margin-bottom: 0px;">如果希望在不支持CSS动画的浏览器中使用自定义样式,应该将其写在这里;然而,在该例中,我们不需要除动画效果以外的任何自定义样式。</p>

<p style="margin-bottom: 0px;"> </p>

<p style="margin-bottom: 0px;">关键帧是用{{ cssxref("@keyframes") }}定义的。该例中,我们只使用了两个关键帧。第一个出现在0%(此例中使用了别名<code>from</code>)处,此处元素的左边距为100%(即位于容器的右边界),宽为300%(即容器宽度的3倍),使得在动画的第一帧中标题位于浏览器窗口右边界之外。</p>

<p style="margin-bottom: 0px;"> </p>

<p style="margin-bottom: 0px;">第二帧出现在100%(此例中使用了别名<code>to</code>)。元素的左边距设为0%,宽设为100%,使得动画结束时元素与窗口左边界对齐。</p>

<pre class="brush: html">&lt;p&gt;The Caterpillar and Alice looked at each other for some time in silence:
at last the Caterpillar took the hookah out of its mouth, and addressed
her in a languid, sleepy voice.&lt;/p&gt;
</pre>

<p>{{EmbedLiveSample("文本滑过浏览器窗口","100%","250")}}</p>

<h3 id="增加关键帧">增加关键帧</h3>

<p style="margin-bottom: 0px;">让我们给上面的示例中添加一个关键帧,比如标题的字号先变大然后恢复正常,添加这个关键帧十分简单:</p>

<p style="margin-bottom: 0px;"> </p>

<pre class="brush: css">75% {
  font-size: 300%;
  margin-left: 25%;
  width: 150%;
}
</pre>

<pre class="brush: css hidden">p {
  animation-duration: 3s;
  animation-name: slidein;
}

@keyframes slidein {
  from {
    margin-left: 100%;
    width: 300%;
  }

  to {
    margin-left: 0%;
    width: 100%;
  }
}
</pre>

<pre class="brush: html hidden">&lt;p&gt;The Caterpillar and Alice looked at each other for some time in silence:
at last the Caterpillar took the hookah out of its mouth, and addressed
her in a languid, sleepy voice.&lt;/p&gt;
</pre>

<p>在动画序列执行到75%的时候,标题元素的左边距为25%,宽度为150%。</p>

<p>{{EmbedLiveSample("增加关键帧","100%","250")}}</p>

<h3 id="重复动画">重复动画</h3>

<p>{{ cssxref("animation-iteration-count") }}用以指定动画重复的次数,仅仅使用该属性就能使动画重复播放。在该例中,设该属性为<code>infinite</code>以使动画无限重复</p>

<pre class="brush: css">p {
  animation-duration: 3s;
  animation-name: slidein;
  animation-iteration-count: infinite;
}
</pre>

<pre class="brush: css hidden">@keyframes slidein {
  from {
    margin-left: 100%;
    width: 300%;
  }

  to {
    margin-left: 0%;
    width: 100%;
  }
}
</pre>

<pre class="brush: html hidden">&lt;p&gt;The Caterpillar and Alice looked at each other for some time in silence:
at last the Caterpillar took the hookah out of its mouth, and addressed
her in a languid, sleepy voice.&lt;/p&gt;
</pre>

<p>{{EmbedLiveSample("重复动画","100%","250")}}</p>

<h3 id="来回运动">来回运动</h3>

<p>上面实现了动画的重复播放,但是每次动画开始时总跳回开始位置显得很怪异。我们真正想要的是标题来回滑动,这时只需要设置{{ cssxref("animation-direction") }}属性为<code>alternate</code></p>

<pre class="brush: css">p {
  animation-duration: 3s;
  animation-name: slidein;
  animation-iteration-count: infinite;
  animation-direction: alternate;
}
</pre>

<pre class="brush: css hidden">@keyframes slidein {
  from {
    margin-left: 100%;
    width: 300%;
  }

  to {
    margin-left: 0%;
    width: 100%;
  }
}
</pre>

<pre class="brush: html hidden">&lt;p&gt;The Caterpillar and Alice looked at each other for some time in silence:
at last the Caterpillar took the hookah out of its mouth, and addressed
her in a languid, sleepy voice.&lt;/p&gt;
</pre>

<p>{{EmbedLiveSample("来回运动","100%","250")}}</p>

<h3 id="使用动画事件">使用动画事件</h3>

<div>利用动画事件可以更好的控制动画和信息。这些事件由 {{ domxref("event/AnimationEvent", "AnimationEvent") }}对象表示,可探测动画何时开始结束和开始新的循环。每个事件包括动画发生的时间和触发事件的动画名称。</div>

<div> </div>

<div>我们将修改滑动文本示例,输出每个动画事件出现时的信息。</div>

<pre class="brush: css">.slidein {
  -moz-animation-duration: 3s;
  -webkit-animation-duration: 3s;
  animation-duration: 3s;
  -moz-animation-name: slidein;
  -webkit-animation-name: slidein;
  animation-name: slidein;
  -moz-animation-iteration-count: 3;
  -webkit-animation-iteration-count: 3;
  animation-iteration-count: 3;
  -moz-animation-direction: alternate;
  -webkit-animation-direction: alternate;
  animation-direction: alternate;
}

@-moz-keyframes slidein {
  from {
    margin-left:100%;
    width:300%
  }

  to {
    margin-left:0%;
    width:100%;
  }
}

@-webkit-keyframes slidein {
  from {
    margin-left:100%;
    width:300%
  }

  to {
   margin-left:0%;
   width:100%;
 }
}

@keyframes slidein {
  from {
    margin-left:100%;
    width:300%
  }

  to {
   margin-left:0%;
   width:100%;
 }
}</pre>

<h4 id="添加动画事件监听器">添加动画事件监听器</h4>

<p>我们使用JavaScript代码监听所有三种可能的动画事件,<code>setup()</code>方法设置事件监听器,当文档第一次加载完成时执行该方法。</p>

<pre class="brush: js">var e = document.getElementById("watchme");
e.addEventListener("animationstart", listener, false);
e.addEventListener("animationend", listener, false);
e.addEventListener("animationiteration", listener, false);

e.className = "slidein";
</pre>

<div>以上是非常标准的代码写法,setup()最后设置动画元素的<code>class</code>为slidein,启动动画。</div>

<div> </div>

<div>为什么这样做?因为<code>animationstart</code>事件在动画一开始时就被触发,在我们的示例中,该事件在我们的代码执行前就被触发,所以我们自己通过设置元素的的<code>class</code>来启动动画。</div>

<div> </div>

<h4 id="接收事件">接收事件</h4>

<p>事件传递给<code>listener()</code>函数,代码如下所示</p>

<pre class="brush: js">function listener(e) {
  var l = document.createElement("li");
  switch(e.type) {
    case "animationstart":
      l.innerHTML = "Started: elapsed time is " + e.elapsedTime;
      break;
    case "animationend":
      l.innerHTML = "Ended: elapsed time is " + e.elapsedTime;
      break;
    case "animationiteration":
      l.innerHTML = "New loop started at time " + e.elapsedTime;
      break;
  }
  document.getElementById("output").appendChild(l);
}</pre>

<p style="margin-bottom: 0px;">这段代码同样非常简单,简单地通过{{ domxref("event.type") }}来判断发生的是何种事件,然后添加对应的注解到{{ HTMLElement("ul") }}中。</p>

<p style="margin-bottom: 0px;"> </p>

<p style="margin-bottom: 0px;">输出结果如下所示:</p>

<p style="margin-bottom: 0px;"> </p>

<ul>
 <li>Started: elapsed time is 0</li>
 <li>New loop started at time 3.01200008392334</li>
 <li>New loop started at time 6.00600004196167</li>
 <li>Ended: elapsed time is 9.234000205993652</li>
</ul>

<div>注意以上时间非常接近预期时间,但不是完全相等。也要注意在最后一个周期完成后,不会触发<code>animationiteration</code>事件,而触发<code>animationend</code>事件。</div>

<div> </div>

<h4 id="HTML代码">HTML代码</h4>

<p>下面是示例中的用到的HTML代码:</p>

<pre class="brush: html">&lt;body&gt;
  &lt;h1 id="watchme"&gt;Watch me move&lt;/h1&gt;
  &lt;p&gt;This example shows how to use CSS animations to make &lt;code&gt;h1&lt;/code&gt; elements
  move across the page.&lt;/p&gt;
  &lt;p&gt;In addition, we output some text each time an animation event fires, so you can see them in action.&lt;/p&gt;
  &lt;ul id="output"&gt;
  &lt;/ul&gt;
&lt;/body&gt;
</pre>

<p>{{EmbedLiveSample('使用动画事件', '600', '300')}}</p>

<h2 id="See_also">See also</h2>

<ul>
 <li>{{ domxref("AnimationEvent", "AnimationEvent") }}</li>
 <li><a href="/en-US/docs/CSS/CSS_animations/Detecting_CSS_animation_support" title="en/CSS/CSS animations/Detecting CSS animation support">Detecting CSS animation support</a></li>
 <li><a href="https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Using_CSS_transitions">Using CSS transitions</a></li>
</ul>