From 33058f2b292b3a581333bdfb21b8f671898c5060 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:40:17 -0500 Subject: initial commit --- .../detecting_css_animation_support/index.html | 91 ++++++ files/zh-cn/web/css/css_animations/index.html | 82 +++++ files/zh-cn/web/css/css_animations/tips/index.html | 100 ++++++ .../css_animations/using_css_animations/index.html | 359 +++++++++++++++++++++ 4 files changed, 632 insertions(+) create mode 100644 files/zh-cn/web/css/css_animations/detecting_css_animation_support/index.html create mode 100644 files/zh-cn/web/css/css_animations/index.html create mode 100644 files/zh-cn/web/css/css_animations/tips/index.html create mode 100644 files/zh-cn/web/css/css_animations/using_css_animations/index.html (limited to 'files/zh-cn/web/css/css_animations') diff --git a/files/zh-cn/web/css/css_animations/detecting_css_animation_support/index.html b/files/zh-cn/web/css/css_animations/detecting_css_animation_support/index.html new file mode 100644 index 0000000000..75b845f57e --- /dev/null +++ b/files/zh-cn/web/css/css_animations/detecting_css_animation_support/index.html @@ -0,0 +1,91 @@ +--- +title: 检测CSS动画的支持性 +slug: Web/CSS/CSS_Animations/Detecting_CSS_animation_support +translation_of: Web/CSS/CSS_Animations/Detecting_CSS_animation_support +--- +

{{CSSRef}}

+ +

CSS 动画 使仅用CSS属性来使内容呈现动画效果成为一种可能,然而,某些时候CSS动画属性并不能生效,此时,我们希望能够通过javascript代码来实现相似的动画效果。针对此种情况,本文基于Chris Heilmann的 this blog post 对该技术进行了示范。

+ +

CSS动画支持检测

+ +

下面的代码将检测CSS动画的支持性是否是有效的。

+ +
var animation = false,
+    animationstring = 'animation',
+    keyframeprefix = '',
+    domPrefixes = 'Webkit Moz O ms Khtml'.split(' '),
+    pfx  = '',
+    elm = document.createElement('div');
+
+if( elm.style.animationName !== undefined ) { animation = true; }
+
+if( animation === false ) {
+  for( var i = 0; i < domPrefixes.length; i++ ) {
+    if( elm.style[ domPrefixes[i] + 'AnimationName' ] !== undefined ) {
+      pfx = domPrefixes[ i ];
+      animationstring = pfx + 'Animation';
+      keyframeprefix = '-' + pfx.toLowerCase() + '-';
+      animation = true;
+      break;
+    }
+  }
+}
+
+ +

首先先定义几个变量,并通过初始化animation 为false来假设不支持CSS动画属性,先设置animationstring变量为animation并在稍后进行修改。创建一个浏览器前缀的数组用来循环遍历并设置pfx前缀为空字符串。 

+ +

然后,检测创建的elm元素的style属性集合中{{ cssxref("animation-name") }} 属性是否被设置,如果被设置,则意味着着浏览器支持CSS animation属性,而不需要加任何前缀,然而到目前,还没有任何浏览器实现(译者:chrome中试验了一下是可以的);

+ +

如果浏览器不支持无前缀的animation,那么animation变量值仍为false,遍历所有可能的浏览器前缀,由于所有的主流浏览器现在都在该属性前加了前缀,因此在AnimationName 前加上前缀即可。

+ +

当代码执行完,如果浏览器不支持CSS animation属性,则返回animation 为false,否则为true。如果animation为true,则所有animation 相关属性名称以及keyframes属性前缀都是检测到的正确的,因此,如果使用firefox,属性名称就是MozAnimation,keyframes前缀就是-moz-,如果使用chrome,属性为WebkitAnimation ,keyframes前缀为 -webkit-。注意,浏览器是不方便在驼峰法和连字符法之间进行切换的。

+ +

针对不同浏览器使用正确语法实现动画效果

+ +

现在可以知道,无论浏览器是否支持CSS animation,均可以实现动画效果。

+ +
if( animation === false ) {
+
+  // animate in JavaScript fallback
+
+} else {
+  elm.style[ animationstring ] = 'rotate 1s linear infinite';
+
+  var keyframes = '@' + keyframeprefix + 'keyframes rotate { '+
+                    'from {' + keyframeprefix + 'transform:rotate( 0deg ) }'+
+                    'to {' + keyframeprefix + 'transform:rotate( 360deg ) }'+
+                  '}';
+
+  if( document.styleSheets && document.styleSheets.length ) {
+
+      document.styleSheets[0].insertRule( keyframes, 0 );
+
+  } else {
+
+    var s = document.createElement( 'style' );
+    s.innerHTML = keyframes;
+    document.getElementsByTagName( 'head' )[ 0 ].appendChild( s );
+
+  }
+
+}
+
+ +

以上代码主要根据animation的值来进行不同的操作,如果为false,则需要执行javascript脚本来实现动画效果,否则,就用javascript来创建所需要的CSS animation 效果。

+ +

设置animation属性是很简单的,可以在style属性集合中简单的更新它的值。然而,增加keyframes是有难度的,由于它们不能够通过传统的css语法来定义。(虽然这样使得它们更加灵活,但是通过脚本来定义更加不易)

+ +

使用javascript来定义keyframes,需要将其具体语法写为字符串。为了创建keyframes变量,在构建keyframes时要在其所有属性前加前缀,该变量包含完整的所有动画序列所需要的keyframes描述。

+ +

下一个任务是将创建的keyframes添加到实际的CSS中。首先要检查是否在document中存在CSStylesheet,如果存在,则能够简单的将keyframes值插入到CSSstylesheet中。

+ +

如果不存在CSSstylesheet,创建一个新的 {{ HTMLElement("style") }} 元素,并将keyframes设置为其内容。然后将新的{{ HTMLElement("style") }}元素插入到document 的head中,从而将新的style sheet添加到了html文档中。

+ +

在JSFiddle中查看

+ +

更多

+ + diff --git a/files/zh-cn/web/css/css_animations/index.html b/files/zh-cn/web/css/css_animations/index.html new file mode 100644 index 0000000000..17c3ab84a3 --- /dev/null +++ b/files/zh-cn/web/css/css_animations/index.html @@ -0,0 +1,82 @@ +--- +title: CSS Animations +slug: Web/CSS/CSS_Animations +tags: + - CSS + - CSS Animations + - Experimental + - Overview + - Reference +translation_of: Web/CSS/CSS_Animations +--- +

{{CSSRef}}{{SeeCompatTable}}

+ +

CSS Animations 是CSS的一个模块,它定义了如何用关键帧来随时间推移对CSS属性的值进行动画处理。关键帧动画的行为可以通过指定它们的持续时间,它们的重复次数以及它们如何重复来控制。

+ +

参考

+ +

CSS 属性

+ +
+ +
+ +

CSS At-规则

+ +
+ +
+ +

指南

+ +
+
检测CSS动画支持
+
描述用于检测浏览器是否支持CSS动画的技术。
+
使用CSS动画
+
关于如何使用CSS创建动画的分步教程,本文介绍每个相关的CSS属性和规则,并解释它们如何交互。
+
CSS 动画提示
+
提示和技巧,以帮助您在您的内容中充分利用CSS动画。目前提供了一种用于重播已经运行到完成的动画的技术,这是API本身不支持的。
+
+ +

规范

+ + + + + + + + + + + + + + + + +
规范进度备注
{{ SpecName('CSS3 Animations') }}{{ Spec2('CSS3 Animations') }}初始定义。
+ +

浏览器兼容性

+ +
+

{{Compat("css.properties.animation")}}

+
+ +

参考

+ + diff --git a/files/zh-cn/web/css/css_animations/tips/index.html b/files/zh-cn/web/css/css_animations/tips/index.html new file mode 100644 index 0000000000..86de523b3a --- /dev/null +++ b/files/zh-cn/web/css/css_animations/tips/index.html @@ -0,0 +1,100 @@ +--- +title: CSS Animations tips and tricks +slug: Web/CSS/CSS_Animations/Tips +translation_of: Web/CSS/CSS_Animations/Tips +--- +
{{cssref}}
+ +

CSS 动画使得您能够实现一些难以置信的效果点缀您的页面或者应用程序 。 然而, 有些您想实现的东西表现的并不浅显易懂,或者没法使您立马想到一种聪明的解决办法。这篇文章集合一个一些温馨贴士和技巧,从而帮助您更轻松地工作,这其中包括了如何使一个已经停止的动画重新开始播放。

+ +

重新播放动画

+ +

CSS 动画的规范并没有提供使得动画重新激活的方法。在元素上调用resetAnimation() 并不生效,您也不能直接通过设置元素的 {{cssxref("animation-play-state")}}使得动画重新“跑起来”。事实上,你必须使用一些技巧使得已经停止的动画重新播放。

+ +

这有一种我们认为足够稳定和可靠的方法推荐给您。

+ +

HTML 内容

+ +

首先,让我们定义一个我们想要添加动画的元素{{HTMLElement("div")}} 以及一个“播放”或“重播”动画的按钮。

+ +
<div class="box">
+</div>
+
+<div class="runButton">Click me to run the animation</div>
+ +

CSS 内容

+ +

现在我们将使用CSS定义动画本身。为了简洁,有些并不重要的CSS(如“播放”按钮的样式)并没有显示在这里。

+ + + +
@keyframes colorchange {
+  0% { background: yellow }
+  100% { background: blue }
+}
+
+.box {
+  width: 100px;
+  height: 100px;
+  border: 1px solid black;
+}
+
+.changing {
+  animation: colorchange 2s;
+}
+ +

这里有两个类。 "box" 类基本表述了box的外观,它不包含任何动画信息。动画的细节包含在"changing" 类, 它描述了名为 "colorchange" 的{{cssxref("@keyframes")}} 应该这持续两秒的时间段播放动画。

+ +

注意,正因为如此,这个box在这里不触发任何动画效果, 因此他不会动起来。

+ +

JavaScript 内容

+ +

接下来我们将看看 JavaScript的部分如何工作。这里关键的部分在 play() 方法中, 他在用户点击“播放”按钮时被触发。

+ +
function play() {
+  document.querySelector(".box").className = "box";
+  window.requestAnimationFrame(function(time) {
+    window.requestAnimationFrame(function(time) {
+      document.querySelector(".box").className = "box changing";
+    });
+  });
+}
+ +

这看起来有点奇怪,不是么?这是因为重新播放动画的唯一方法是删除动画效果,让文档重新计算样式以使得它知道您已经设置了它,然后再将动画效果加回该元素。要实现这个,我们必须更具创造性。 

+ +

这里是play() 方法被调用时发生的事情:

+ +
    +
  1. box的CSS类列表被重置为"box" 。这么做的效果是移除了在这个box上的其他类属性, 包括处理动画的 "changing"类。换句话说,我们从box元素上删除了动画效果。然而,改变类属性列表在样式被重新计算完成或者发生刷新事件之前并不会生效。
  2. +
  3. 为了确保样式被重新计算我们使用 {{domxref("window.requestAnimationFrame()")}},同时设置了一个回调。我们的回调在下一次重绘页面之前被调用。问题是由于它在重绘之前被调用,而此时样式还没有被真正重新计算。
  4. +
  5. 我们的回调聪明地调用了requestAnimationFrame() 方法!这一次,回调在下一次重绘之前被调用,这发成在样式被重新计算之后。回调在box元素上添加"changing" 类,使得重绘后重新触发动画。
  6. +
+ +

当然,我们同样需要在“播放”按钮上添加事件处理方法使其生效:

+ +
document.querySelector(".runButton").addEventListener("click", play, false);
+ +

结论

+ +

{{ EmbedLiveSample('Run_an_animation_again', 320, 160) }}

+ +

另见

+ + diff --git a/files/zh-cn/web/css/css_animations/using_css_animations/index.html b/files/zh-cn/web/css/css_animations/using_css_animations/index.html new file mode 100644 index 0000000000..3cdd7cd988 --- /dev/null +++ b/files/zh-cn/web/css/css_animations/using_css_animations/index.html @@ -0,0 +1,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 +--- +

{{SeeCompatTable}}{{CSSRef}}

+ +

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

+ +

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

+ +
    +
  1. 能够非常容易地创建简单动画,你甚至不需要了解JavaScript就能创建动画。
  2. +
  3. 动画运行效果良好,甚至在低性能的系统上。渲染引擎会使用跳帧或者其他技术以保证动画表现尽可能的流畅。而使用JavaScript实现的动画通常表现不佳(除非经过很好的设计)。
  4. +
  5. 让浏览器控制动画序列,允许浏览器优化性能和效果,如降低位于隐藏选项卡中的动画更新频率。
  6. +
+ +

配置动画

+ +

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

+ +

{{ cssxref("animation") }}的子属性有:

+ +

 

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

 

+ +

使用keyframes定义动画序列

+ +

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

+ +

 

+ +

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

+ +

 

+ +

也可包含额外可选的关键帧,描述动画开始和结束之间的状态。

+ +

 

+ +

示例

+ +
注意: 这里的示例没有在CSS动画属性上使用任何前缀,Webkit内核浏览器或者早期版本浏览器可能需要前缀,下面的实例包含了-webkit-前缀。
+ +

文本滑过浏览器窗口

+ +

该例中{{ HTMLElement("p") }} 元素由浏览器窗口右边滑至左边

+ +
p {
+  animation-duration: 3s;
+  animation-name: slidein;
+}
+
+@keyframes slidein {
+  from {
+    margin-left: 100%;
+    width: 300%;
+  }
+
+  to {
+    margin-left: 0%;
+    width: 100%;
+  }
+}
+
+ +

{{ cssxref("animation-duration") }}属性指定 {{ HTMLElement("p") }} 上的动画从开始到结束耗费3秒,{{ cssxref("@keyframes") }} 指定使用名字为"slidein"的关键帧。

+ +

 

+ +

如果希望在不支持CSS动画的浏览器中使用自定义样式,应该将其写在这里;然而,在该例中,我们不需要除动画效果以外的任何自定义样式。

+ +

 

+ +

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

+ +

 

+ +

第二帧出现在100%(此例中使用了别名to)。元素的左边距设为0%,宽设为100%,使得动画结束时元素与窗口左边界对齐。

+ +
<p>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.</p>
+
+ +

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

+ +

增加关键帧

+ +

让我们给上面的示例中添加一个关键帧,比如标题的字号先变大然后恢复正常,添加这个关键帧十分简单:

+ +

 

+ +
75% {
+  font-size: 300%;
+  margin-left: 25%;
+  width: 150%;
+}
+
+ + + + + +

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

+ +

{{EmbedLiveSample("增加关键帧","100%","250")}}

+ +

重复动画

+ +

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

+ +
p {
+  animation-duration: 3s;
+  animation-name: slidein;
+  animation-iteration-count: infinite;
+}
+
+ + + + + +

{{EmbedLiveSample("重复动画","100%","250")}}

+ +

来回运动

+ +

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

+ +
p {
+  animation-duration: 3s;
+  animation-name: slidein;
+  animation-iteration-count: infinite;
+  animation-direction: alternate;
+}
+
+ + + + + +

{{EmbedLiveSample("来回运动","100%","250")}}

+ +

使用动画事件

+ +
利用动画事件可以更好的控制动画和信息。这些事件由 {{ domxref("event/AnimationEvent", "AnimationEvent") }}对象表示,可探测动画何时开始结束和开始新的循环。每个事件包括动画发生的时间和触发事件的动画名称。
+ +
 
+ +
我们将修改滑动文本示例,输出每个动画事件出现时的信息。
+ +
.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%;
+ }
+}
+ +

添加动画事件监听器

+ +

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

+ +
var e = document.getElementById("watchme");
+e.addEventListener("animationstart", listener, false);
+e.addEventListener("animationend", listener, false);
+e.addEventListener("animationiteration", listener, false);
+
+e.className = "slidein";
+
+ +
以上是非常标准的代码写法,setup()最后设置动画元素的class为slidein,启动动画。
+ +
 
+ +
为什么这样做?因为animationstart事件在动画一开始时就被触发,在我们的示例中,该事件在我们的代码执行前就被触发,所以我们自己通过设置元素的的class来启动动画。
+ +
 
+ +

接收事件

+ +

事件传递给listener()函数,代码如下所示

+ +
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);
+}
+ +

这段代码同样非常简单,简单地通过{{ domxref("event.type") }}来判断发生的是何种事件,然后添加对应的注解到{{ HTMLElement("ul") }}中。

+ +

 

+ +

输出结果如下所示:

+ +

 

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

HTML代码

+ +

下面是示例中的用到的HTML代码:

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

{{EmbedLiveSample('使用动画事件', '600', '300')}}

+ +

See also

+ + -- cgit v1.2.3-54-g00ecf