CSS アニメーションの基礎

Category : CSS

今さらながら CSS animation の使い方が分かってきたので、プロパティなどを簡単にまとめておきたいと思います。
これを書くにあたって、以下の2つを参考にしました。

上のは dev.w3.org にある、2011年7月25日版のエディターズドラフトです。
ちなみに www.w3.org にある仕様は CSS Animations Module Level 3 です。これを書いている現在、こっちは 2009年3月20日版 が最新となっています。
基本的に2011年7月25日版のエディターズドラフトをベースに説明したいと思います。なので、現在のブラウザの実装とは異なることもあります。

2つ目のは Mozilla Developer Network のドキュメントです。日本語版 もあります。
アニメーションに限らず、MDN のドキュメントはとても分かりやすいのでお勧めです。日本語で読めるものも多いです。

これから出てくるプロパティなどは、現在、どのブラウザで使うにしてもベンダー接頭辞が必要ですが、記事内には書きません。

@keyframes

アニメーションを定義する@ルールです。
これを使ってアニメーションの流れを指定することができます。

@keyframes 識別子 {
 from {
   ...
 }
 to {
   ...
 }
}

のように記述します。

識別子は CSS Values and Units Module Level 3 で決められた <identifier> 形式で書く必要があります。
これは ASCII の範囲の文字で、大文字と小文字は区別されます。

キーフレームのセレクタはパーセンテージ、from または to で記述します。これらはカンマ区切りにより複数指定が可能です。
from0% と等しく、to100% と等しいです。

また、2009年3月20日版 のワーキングドラフトでは、from(0%)to(100%) は必須と書かれていますが、2011年7月25日のエディターズドラフトでは、それらが定義されていない場合はユーザーエージェントが補完する、となっています。
これは最終的にどうなるか分かりませんが、ちゃんと書いておいた方がいいと思います。分かりにくくなりますしね。

この記事で使うアニメーションルールを作りました。
ここから先はこれを使って説明します。

@keyframes left-to-right {
  from {
    left: 0;
  }
  to {
    left: 570px;
  }
}

animation-name

どのアニメーションを使用するか指定します。値には @keyframes で指定した識別子を指定します。

div {
  animation-name: left-to-right;
}

animation-duration

1度のアニメーション周期の完了までの時間を指定します。
値には CSS Values and Units Module Level 3 で決められた <time> 形式で書く必要があります。

デフォルトは 0s です。負の値を指定すると、それは 0s として扱われます。
このとき、animation-fill-mode (後述) は適用されていて、その値が backwards であった場合、任意の遅延時間内にキーフレームの 0% で指定された値が表示されます。forwards の場合は、100% で指定された値が保持されます。
また、アニメーションイベントも発生します。

では、実際に見てみようと思います。
HTML は以下のようなものを使います。

<div id="container">
  <div class="test1">1</div>
  <div class="test2">2</div>
  ...
</div>

キーフレーム指定は前述のものを使い、次のような指定をします。
(あんまり関係のない部分は省略しています)

#container > div {
  position      : relative;
  animation-name: left-to-right;
}

.test1 {
  animation-duration: 0.5s;
}

.test2 {
  animation-duration: 1s;
}

.test3 {
  animation-duration: 1.5s;
}

.test4 {
  animation-duration: 2s;
}

aniamtion-duration のデモ

animation-timing-function

どのようなアニメーションを適用するかを指定します。
指定できる値は transition-timing-function と同じです。
CSS Transitions に詳しく説明されています。
一覧にするとこうなります。

ease
cubic-bezier(0.25, 0.1, 0.25, 1) と同じ。
linear
cubic-bezier(0, 0, 1, 1) と同じ。
ease-in
cubic-bezier(0.42, 0, 1, 1) と同じ。
ease-out
cubic-bezier(0, 0, 0.58, 1) と同じ。
ease-in-out
cubic-bezier(0.42, 0, 0.58, 1) と同じ。
cubic-bezier()
3次ベジェ曲線による指定を行います。
step-start
steps(1, start) と同じ。
step-end
steps(1, end) と同じ。
steps()
指定した回数で等間隔に分割して実行されます。

デフォルトは ease です。

文字だけだと説明しづらいので、cubic-bezier()steps() については CSS Transitions に載っている図を参考にしてください。

とりあえず、各指定を使ったサンプルを作りました。
これでどういう動きか分かるかと思います。

.test1 {
  animation-timing-function: ease;
}

.test2 {
  animation-timing-function: linear;
}

.test3 {
  animation-timing-function: ease-in;
}

.test4 {
  animation-timing-function: ease-out;
}

.test5 {
  animation-timing-function: ease-in-out;
}

.test6 {
  animation-timing-function: cubic-bezier(1, 0, 1, 0);
}

.test7 {
  animation-timing-function: step-start;
}

.test8 {
  animation-timing-function: step-end;
}

.test9 {
  animation-timing-function: steps(10, start);
}

.test10 {
  animation-timing-function: steps(10, end);
}

animation-timing-function のデモ 1

また、これらの関数はアニメーション全体ではなく、キーフレーム間で実行されます。
前出の @keyframes left-to-right に指定を1つ加えてみると分かりやすいです。
animation-timing-function の指定は1つ前のデモと同じです。

@keyframes left-to-right {
  from { left: 0; }
  50%  { left: 285px; }
  to   { left: 570px; }
}

animation-timing-function のデモ 2

正直、cubic-bezier() を動きを予想しながら手書きするのは厳しいというか無理っぽいので、ジェネレータを使ったほうがいいと思います。
そういったものはオンラインにもありますので、いくつか紹介しておきます。

お勧めは上2つです。

animation-iteration-count

アニメーションの実行回数を指定します。
デフォルトは 1 です。

数値に負の値を指定した場合、0 として扱われます。
また、数値の他に infinite を指定できます。これを指定するとアニメーションは無限に繰り返されます。

animation-iteration-count のデモ

animation-direction

アニメーションの方向を指定します。
デフォルトは normal です。

alternate という値を指定すると、奇数回のアニメーションはノーマルな状態で実行され、偶数回のアニメーションは逆方向に実行されます。
このとき animation-timing-function の指定も逆になります。

animation-iteration-count で使ったデモに animation-direction:alternate; を指定してみました。

animation-direction のデモ

animation-timing-function:ease; の動きが逆になっているのが分かるかと思います。

animation-play-state

アニメーションの実行状態を示すプロパティです。
デフォルトは running です。

paused を指定することで、アニメーションを一時停止することができます。
一時停止したアニメーションを再開する場合、停止した時点から再開されます。

また、アニメーションの状態を取得する際にも使用されます。

animation-delay

アニメーションをいつ開始するかを指定するプロパティです。
値は <time> 形式で記述します。デフォルトは 0s です。

0 の指定をした場合、アニメーションが適用されたら即座にアニメーションが実行されます。
1s の場合だと、アニメーションが適用されてから1秒後にアニメーションが始まるわけです。 負の値、たとえば -1s などは 0 として扱われ、適用後即実行となりますが、アニメーションが1秒経過した状態から始まります。

下記のようなサンプルを作りましたので、ご確認ください。

.test1 {
  animation-delay: -1s;
}

.test2 {
  animation-delay: 0;
}

.test3 {
  animation-delay: 1s;
}

.test4 {
  animation-delay: 2s;
}

animation-delay のデモ

animation-fill-mode

アニメーションの実行前や後にどういうスタイルを適用するのかを指定します。
指定できる値は以下のようになっています。

none
キーフレームで指定されたスタイルは、アニメーションの前後には適用されません。
forwards
アニメーションの実行後にキーフレームの最後(通常は to, 100%)の指定が適用されます。ただし、animation-directionalternate 且つ animation-iteration-count の値が偶数の場合は、キーフレームの最初(通常は from, 0%)が適用されます。
backwards
アニメーションが適用されたら即座にキーフレームの最初のスタイル指定を適用します。これは animation-delay で指定された遅延時間の間も維持されます。
both
forwardsbackwards の両方が適用されます。アニメーション実行前には backwards が、実行後には forwards があると考えると分かりやすいかと思います。

デフォルトは none です。

ちょっと組み合わせがややこしいので、分割してサンプルを作りました。
また、キーフレームの指定も変更しています。
アニメーション適用前は left:0; の状態です。

@keyframes left-to-right {
  from {
    left: 285px;
  }
  to {
    left: 570px;
  }
}

animation-fill-mode 以外のアニメーションの指定は次のようになっています。

/* 共通部分 */
#container > div {
  animation-name           : left-to-right;
  animation-duration       : 3s;
  animation-timing-function: ease;
  animation-direction      : normal;
}

.test1 {
  animation-iteration-count: 1;
  animation-direction      : normal;
  animation-delay          : 0s;
}

.test2 {
  animation-iteration-count: 1;
  animation-direction      : alternate;
  animation-delay          : 0s;
}

.test3 {
  animation-iteration-count: 1;
  animation-direction      : normal;
  animation-delay          : 1s;
}

.test4 {
  animation-iteration-count: 1;
  animation-direction      : alternate;
  animation-delay          : 1s;
}

.test5 {
  animation-iteration-count: 2;
  animation-direction      : normal;
  animation-delay          : 0s;
}

.test6 {
  animation-iteration-count: 2;
  animation-direction      : alternate;
  animation-delay          : 0s;
}

.test7 {
  animation-iteration-count: 2;
  animation-direction      : normal;
  animation-delay          : 1s;
}

.test8 {
  animation-iteration-count: 2;
  animation-direction      : alternate;
  animation-delay          : 1s;
}

animation-fill-mode:none; の場合。
何も指定しないとこれになります。

animation-fill-mode:none; のデモ

アニメーション適用時(ここではページロード直後)、animation-delay の指定のあるものが最初は左端にあって、アニメーション開始と同時に位置が変更されているのが分かるかと思います。
また、アニメーションが完了すると全ての要素が左端に配置されます。

次は forwards の場合。

animation-fill-mode:forwards; のデモ

アニメーション適用時は none の指定のときと同じですね。
アニメーション完了時には、それぞれ最後のキーフレームの位置に留まっています。

backwards の場合。

animation-fill-mode:backwards; のデモ

アニメーション適用時、遅延のあるものも既に from の位置に配置されているのが分かります。
完了時は none のときと同じです。

both の場合。

animation-fill-mode:both; のデモ

アニメーション適用時には backwards、完了時には forwards と同じような動きをしています。
これで両方の特徴を持っているのが分かります。

animation ショートハンドプロパティ

ここまで各プロパティを見てきましたが、結構数があるので書くのが非常に面倒です。
一つ一つ指定していたらこんな感じになります。

div {
  animation-name           : left-to-right;
  animation-duration       : 3s;
  animation-timing-function: linear;
  animation-delay          : 1s;
  animation-iteration-count: 2;
  animation-direction      : normal;
  animation-fill-mode      : forwards;
}

これだけでも多いのに、現状だと更に各ベンダープレフィックスをつけて、1つのプロパティを5種類書かなくてはいけません。計35行です。
(Opera はどうなるか分かりませんが、一応つけるとすると)

これを短縮形で書くことで少し楽になります。
書き方は、2011年7月25日版のエディターズドラフトの時点で、次のようになります。
(見やすくするために改行しています)

animation: name
           duration
           timing-function
           delay
           iteration-count
           direction
           fill-mode

デフォルトは各プロパティに従います。
<time> 指定は、1番目が animation-duration、2番目が animation-delay となりますので注意してください。

これに先ほどのものを当てはめると、

div {
  animation: left-to-right 3s linear 1s 2 normal forwards;
}

となります。

ただ、エディターズドラフトを見ると、スラッシュ(/)を使った代替案が書かれています。
それは 3s/1s のようなもので duration/delay とするというものです。
このあたりは今後どうなるか分かりませんで気をつけたいところです。

イベント

JavaScript で扱うアニメーションのイベントです。

animationstart
アニメーション開始時のイベントです。
animation-delay が指定されている場合は、遅延時間が完了してから発生します。
animationend
アニメーション終了時のイベントです。アニメーションが完了したときに発生します。
animationiteration
animation-iteration-count1 より大きい場合にのみ発生します。
これはアニメーションが1周するごとに発生します。

現在、Firefox では上記の通り全て小文字で接頭辞なしの記述ですが、
webkit ブラウザでは webkitAnimationStart, webkitAnimationEnd, webkitAnimationIteration
IE10 では MSAnimationStart, MSAnimationEnd, MSAnimationIteration
となっています。

最後に

最後まで読んでくださってありがとうございます。お疲れ様でした。

この記事はあくまでも2011年10月序盤で確認できる仕様を元にしたものであり、今後変更がある可能性があります。
また、説明の足りない部分や解釈の間違い、英文の誤読がある可能性もあります。

ですので、一度は仕様を見ておいてほしいと思います。

Trackbacks & Pingbacks

Leave a Reply