この翻訳は不完全です。英語から この記事を翻訳 してください。

CSSアニメーションはドキュメントとアプリを構成する要素を使って驚くべき事を行うことを可能にします。しかしながら、行いたくても理解しやすくないことがあったり、すぐに思いつかないであろう巧妙な方法があります。この記事は停止したアニメーションをどのように再び実行するのかを含む、あなたの仕事を楽にするかもしれない私達が見つけた秘訣やトリックを集めたものになります。

再度アニメーションを実行する

CSSアニメーションの仕様書では再度アニメーションを実行する方法を提示していません。 要素に魔法の関数resetAnimation()というものはなく、要素のanimation-play-stateを再び"running"に設定することさえもできません。その代わりに、停止したアニメーションをリプレイするための巧妙なトリックを使う必要があります。

ここでの私達が考える停止したアニメーションのリプレイを行う方法はあなたに提案することに対して十分に信頼、安定しています。

HTMLの内容

はじめに、HTMLにアニメーションしてほしい<div>と、アニメーションを再生(またはリプレイ)するためのボタンを定義しましょう。

<div class="box">
</div>

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

CSSの内容

次にCSSを使ってアニメーションそのものを定義しましょう。簡潔さのためにいくつかの重要ではないCSS(”Run”ボタンそのもののスタイル)はここではお見せしません。

@keyframes colorchange {
  0% { background: yellow }
  100% { background: blue }
}

.box {
  width: 100px;
  height: 100px;
  border: 1px solid black;
}

.changing {
  animation: colorchange 2s;
}

ここに2つのクラスがあります。”box”クラスはアニメーション情報を含まないboxの外見の基本的な記述です。アニメーションの詳細は”changing”クラスに含まれており、その中で”colorchange”と名付けられた@keyframesはboxをアニメーションするため2秒間、使われるべきだと書いてあります。

それに伴い注意すべきことは、boxは所定の位置であらゆるアニメーション効果を開始しないと同時に、アニメーションすることはないでしょう。

JavaScript の内容

次にアニメーションを行うためのJavaScriptを見ていきます。このテクニックの内容はplay()関数にあり、ユーザーが"Run"ボタンをクリックした時に呼ばれます。

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

これは奇妙に見受けられるでしょうか?再度アニメーションを実行する唯一の方法はアニメーション効果を取り除くことであるため、あなたが行いたいことをドキュメントに知らせてあげて、ドキュメントにスタイルの再計算させてあげましょう。その時要素に戻るためのアニメーション効果を追加します。 それを実現するためには、私達は創造的でなければなりません。

play()関数が呼び出された時に起きることは以下のものです。

  1. CSSクラスのboxのリストは単純に"box"にリセットされます。そのboxに現在適用されている他のどのクラスを取り除く効果を持ちます。これはアニメーションを扱う"changing"クラスを含めます。言い換えると、boxからアニメーション効果を取り除きます。しかしながら、クラスのリストを変更することはそのスタイルの再計算が完了するまで効果を持たず、更新はその変更を反映するために発生し続けます。
  2. スタイルが再計算されることが確かであるとき、window.requestAnimationFrame()を使用し、コールバックを指定します。コールバックは次のドキュメントの再描画の前に適切に実行されます。問題はそのコールバックの呼び出しが再描画の前であるゆえに、スタイルの再計算はまだ実際に起きてはいないのです。
  3. コールバックは巧妙でもう一度requestAnimationFrame()を呼びます!この時、 そのコールバックは次の再描画の前に実行し、スタイルの再計算はその後に行われます。このコールバックはboxクラスの後ろに"changing"クラスを追加し、そのためクラスを追加したことによる再描画はもう一度要素のアニメーションを始めることでしょう。

もちろん、実際に動作するために"Run"ボタンにイベントハンドラーを追加することは必要です。

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

結果

アニメーションの停止

単純に、要素に適用したanimation-nameを取り除くことはそれの次の状態にジャンプまたは割り込ませます。もし代わりにアニメーションを完了することが好ましいなら、その時は取り除くことは止め、異なるアプローチを試みなければいけません。主要なトリックは次のものです。

  1. 可能なら自身を含めるようアニメーションさせること。これはanimation-direction: alternateを信頼するべきではないことを意味します。 代わりに一回の繰り返しの中で完全なアニメーションを経過するキーフレームアニメーションを明示的に書くべきです。
  2. JavaScriptを使用し、animationiterationイベントが起動する時に使われるアニメーションをクリアーすること。

次のデモは前述のJavaScriptテクニックをどのように利用するかを示します。

.slidein {
  animation-duration: 5s;
  animation-name: slidein;
  animation-iteration-count: infinite;
}

.stopped {
  animation-name: none;
}

@keyframes slidein {
  0% {
    margin-left: 0%;
  }
  50% {
    margin-left: 50%;
  }
  100% {
    margin-left: 0%;
  }
}
<h1 id="watchme">Click me to stop</h1>
let watchme = document.getElementById('watchme')

watchme.className = 'slidein'
const listener = (e) => {
  watchme.className = 'slidein stopped'
}
watchme.addEventListener('click', () =>
  watchme.addEventListener('animationiteration', listener, false)
)

デモ https://jsfiddle.net/morenoh149/5ty5a4oy/

See also

ドキュメントのタグと貢献者

このページの貢献者: mdnwebdocs-bot, tositeru
最終更新者: mdnwebdocs-bot,