CSS3 animationのまとめ(基本編)
前回のtransitionに続き、animationについてもまとめておきます。
transitionよりも長くなりそうなので基本編と発展編に分けたいと思います。
まずは基本編から。
<目次>
animationのできること
transitionは変更前と変更後の2点を結ぶ機能なのに対して、animationではキーフレームでアニメーションを定義できることから、transitionよりも複雑な動きを作成することができます。
例えばページ読み込み時に表示されるローディングgifの代わりにcss animationを使ってリッチな表現が可能です。(参考:待ち時間をもっと楽しく!コピペできるCSSローディングアニメーション38個まとめ)
animationをサポートするブラウザも増えてきた上(というよりは古いブラウザへの対応が減ってきた)、基本的にJavaScriptでのDOMアニメーションよりもパフォーマンスが優れているため、現在はJavaScriptではアニメーション開始のきっかけ(イベント)を作り、アニメーション自体はcss transitionやanimationで表現する、というのが主流になってきています。
対応ブラウザ
IEはtransitionと同じく10以上から対応で、基本的に現在のモダンブラウザであれば利用できます。
androidは4.4までベンダープレフィックスが必要なので、現在はまだ-webkit-
をつけた方が無難です。
詳しくはCan I useをご確認ください。
各プロパティの概要・構文
animation-name
利用する@keyframesの名前を指定します。
つまりどの動きのアニメーションを利用するかの指定です。
selector1 { animation-name: none; /* 初期値。アニメーションさせない意味。 */ } selector2 { animation-name: anim[, <name>[,...]]; /* 複数指定の場合はカンマで区切る */ }
animation-duration
1回のアニメーションが完了するまでの時間。
単位はs
(秒)もしくはms
(ミリ秒)。
selector1 { animation-duration: 0s; /* 初期値。実質、遅延をさせない意味。 */ } selector2 { animation-duration: .3s(300ms)[, <time>[,...]]; /* 複数指定の場合はカンマで区切る */ }
animation-timing-function
3次ベジェ曲線を指定します(基本的にはイージングと考えてOK)。 プロパティ値はtransition-timing-funtionと同じです。
selector1 { animation-timing-function: ease; /* 初期値 */ } selector2 { animation-timing-function: ease, linear[, <function-name>[,...]]; /* 複数指定の場合はカンマで区切る。*/ }
上記の指定では、1回のアニメーション全体のベジェ曲線を指定していますが、@keyframes内でキーフレーム間ごとに再定義が可能です。
▼デモ
基本は右に行って帰ってくるアニメーションです。
demo1では@keyframes内ではイージングを指定していません。
animation-name
定義時にanimation-timing-function:linear;
を指定しているので全体を通して等速で移動します。
demo2ではdemo1をベースに、@keyframes内でanimation-timing-function:steps(4, start)
とanimation-timing-function:steps(8, start)
を設定しています。
デモの通り、行きと帰りのアニメーションで異なったステップ数になったのを確認できます。
demo3ではdemo2をベースに、animation-name
定義時にanimation-timing-function:ease-in;
を指定しています。
最初、私はこのease-inが効いてステップのアニメ含めて全体がease-inのイージングがかかると思っていたのですが、結果は違いました。demo2と全く同じ動きになります。
つまり、@keyframes内でイージングを指定するとそのキーフレーム間はそのイージングが適用されます。全体のイージングは無視されます。
そもそも冒頭で再定義と言っているので当たり前といえば当たり前なのですが…。
demo4ではdemo3をベースに、行きの時だけ@keyframes内でイージングを指定します。
その場合は、行きはそのイージングが適用され、帰りは全体にかけたイージング(ease-in)が適用されます。
animation-delay
アニメーションを開始するまでの遅延時間。
単位はs
(秒)もしくはms
(ミリ秒)。
selector1 { animation-delay: 0s; /* 初期値。実質、遅延をさせない意味。 */ } selector2 { animation-delay: .3s(300ms); /* 0.3秒遅延させる */ } selector3 { animation-delay: .3s(300ms)[, <time>[,...]]; /* 複数指定の場合はカンマで区切る */ }
transition-delayと同じく使い方次第で強力な効果を発揮します。
詳しくは発展編で紹介します。
animation-iteration-count
アニメーションを何回実行するかの指定。
selector1 { animation-iteration-count: 1; /* 初期値。1回だけ実行される。 */ } selector2 { animation-iteration-count: infinite; /* 無限 */ } selector3 { animation-iteration-count: 1[,<number>[,...]]; /* 複数指定の場合はカンマで区切る */ }
▼デモ
codepen.io
基本的にはinfinite
か整数を設定するのですが、小数の指定も可能です。
小数の場合はアニメーションの途中で終了します。たとえば0.6だと全体の60%の位置で終了します。
負の値の場合は0とみなされアニメーションしません。
animation-direction
アニメーションのサイクルごとに実行方向を指定。
selector1 { animation-direction: normal; /* 初期値。順方向のアニメーションのみ実行 */ } selector2 { animation-direction: reverse; /* 毎回逆方向のアニメーションのみ実行。(イージングも逆になる) */ } selector3 { animation-direction: alternate; /* 順方向 → 逆方向を繰り返す。(逆方向時はイージングも逆になる) */ } selector4 { animation-direction: alternate-reverse; /* 逆方向 → 順方向を繰り返す。(逆方向時はイージングも逆になる) */ } selector5 { animation-direction: normal[,<direction>[,...]]; /* 複数指定の場合はカンマで区切る */ }
これは言葉では伝わりにくいのでデモをご覧ください。
基本は右に500px動いたあと、左に250px動くというアニメーションです。イージングはease-in
(最初ゆっくり)を指定しています。
demo1は初期値のnormal
を指定しているので、@keyframesで指定した通りの動きになります。
demo2はreverse
を指定しています。毎回、逆方向(@keyframesの100%→0%)の動きになります。
またイージングも逆になります。今回はease-in
を指定していたので、逆のease-out
(最後ゆっくり)の動きになります。
demo3はalternate
を指定しています。初回normal
の動き → 次回reverse
を繰り返します。
demo4はalternate-reverse
を指定しています。初回reverse
→ 次回normal
を繰り返します。
animation-fill-mode
アニメーションの開始前や終了後に、@keyframesで指定したスタイルを適用するか指定。
selector1 { animation-fill-mode: none; /* 初期値。アニメーション開始前/終了後に@keyframesのスタイルを適用しない */ } selector2 { animation-fill-mode: forwards; /* アニメーション終了後、@keyframesのスタイルを適用*/ } selector3 { animation-fill-mode: backwards; /* アニメーション開始前、@keyframesのスタイルを適用 */ } selector4 { animation-fill-mode: both; /* forwardsとbackwordsの両方を適用 */ } selector5 { animation-fill-mode: none[,<fill-mode>[,...]]; /* 複数指定の場合はカンマで区切る */ }
こちらもまずはデモをご覧ください。
「start」ボタンをクリックすると1秒後にアニメーションが実行されます(今回はアニメーション開始前の状態を見る必要があるので、1秒置いています)。 つまりクリックしてから1秒経つまではアニメーション開始前とみなしてください。
基本のアニメーションは下記になります。
- 透明な状態(非表示)
- 徐々に不透明になりながら右に500px動く
- 左に250px動いて完全に不透明になる
demo1ではanimation-fill-mode
は初期値のnone
のため、アニメーションが開始されてから透明な状態になります。終了後は元の状態に戻ります。
demo2ではforwards
を指定しています。アニメーション終了後、元の状態には戻らず@keyframesでのスタイルを維持します。
demo3ではbackwards
を指定しています。アニメーション開始前、@keyframesのスタイルを適用します。終了後は元の状態に戻ります。
demo4ではboth
を指定しています。forwards
とbackwards
の両方を適用しますので、開始前/終了後ともに@keyframesのスタイルを維持します。
一番利用頻度が高いプロパティ値かと思います。
※注意点
animation-direction
がreverse
もしくはalternate-reverse
の場合、最初のアニメーションの実行が逆方向になるので@keyframesのアニメーションが100%→0%になると説明しました。
その状態で、animation-fill-mode
をbackwards
もしくはboth
にしている場合、私は、アニメーション開始前は@keyframesの100%のスタイル(デモの場合、初期状態から見ると右に250pxの位置にいる)が適用されるのかと思ったのですが、実際確認してみると0%のスタイルが適用され、アニメーション開始されると100%からスタートします。
ややこしいのですが、つまり、animation-directionの指定は、アニメーションの開始前には影響がないと考えるとよいでしょう。
animation-play-state
アニメーションの一時停止/再生を設定。
また、この値を取得することでアニメーションが停止中か実行中かを判断することが可能。
selector1 { animation-play-state: running; /* 初期値。アニメーション実行中を示します。また停止中であった場合は実行させます */ } selector2 { animation-play-state: paused; /* アニメーション停止中を示します。また実行中であった場合はその場で一時停止させます */ }
▼デモ codepen.io
demo1では初期状態をanimation-play-state: runnig;
を設定しているので最初からアニメーションが実行されています。
demo2では反対にanimation-play-state: paused;
にしているためアニメーションが実行されていませんが、@keyframesの最初のスタイルが適用されているのが確認できます。
それぞれ「running」「paused」のボタンをクリックするとアニメーションの再生/一時停止が実行されます。
クリックするたびに、アニメーションが適用されている.box
のanimation-play-stateプロパティの値を取得してその値を「現在アニメーションは」の次に赤字で表示させています。
※問題点
かなり便利なプロパティではあるのですが、私が確認したところだと、iOS(10.1.1)で上記のデモを確認すると「running」「paused」ボタンをクリック(タップ)してもアニメーションが再生/一時停止されませんでした。
ただ、赤字のテキストは切り替わっているので、値は切り替わっているようです。
検索して調べたところstack overflowでもその問題が報告されていました。(css animation-play-state paused doesn't work in ios [duplicate])
解決方法も少し遠回りな気がするので、使用には気を付けたほうがよさそうです。
animation
上記サブプロパティをまとめて記述できるショートハンドプロパティ。
最低限必要になるのは@keyframesの名称とアニメーション完了までの時間を表すanimation-durationです。
省略したプロパティは初期値が設定されます。
簡単に記述できるので最もよく使用します。
selector1 { animation: <keyframesName> 1s; /* 実質、最低限必要な記述。1秒間アニメーションが実行される */ } selector2 { animation: <keyframesName> 1s ease-in .5s infinite alternate both running; /* すべてのプロパティを記述した場合 */ }
transitionの時と同じく記述の順番には少し注意が必要です。
時間をひとつ入力した場合はanimation-duration
と見なされます。animation-delay
を指定したい場合は必ず時間を2つ入力する必要があります。
@keyframesの書き方
下記はそれぞれ違う書き方ですが同じ動きをします。
@keyframes anim1 { 0% { transform: translateX(0); } 50% { transform: translateX(500px); } 100% { transform: translateX(0); } } /* 途中のキーフレームのみ記述 */ @keyframes anim2 { 50% { transform: translateX(500px); } } /* 同じスタイルのフレームはカンマ区切りでまとめて記述できる */ @keyframes anim3 { 0%, 100% { transform: translateX(0); } 50% { transform: translateX(500px); } }
▼デモ
しかし個人的には一番最初のanim1
の記述をおすすめします。
あとでコードを見返したときに頭の中で動きを想像しやすい上、修正などもしやすいからです。
anim2
の場合、開始と終了を明示していません。
この場合、最初から.box
にtransform: translateX(100px);
などの指定があった場合、その地点から500pxまで移動してまた100pxまで戻ります。
この特性を生かせば柔軟なアニメーションの作成ができそうですが、この特性を理解しないと意図しない動きになりえるので要注意です。
animationのイベント
アニメーションのイベントをJavaScriptで取得することが可能です。
利用にはベンダープレフィックスwebkit
を付けたほうがよいでしょう。
IE10にはMS
も付けたほうが良さそうです。(参考:Animation iteration event)
イベントの種類は以下の3つです。
- animationstart アニメーション開始のイベントを取得。
- animationiteration アニメーション実行中のイベントを取得。
- animationend アニメーション終了のイベントを取得。
▼デモ codepen.io
animationiteration
イベントはanimation-iteration-count
が2
以上つまり複数回アニメーションが実行されるときに発生します。1回のみのアニメーションでは発生しません。
animationend
イベントはanimation-iteration-count
がinfinite
つまり無限回実行のときは発生しません。
まとめ
- プロパティの数が多いので、基本的にショートハンドの
animation
を利用する。 animation-direction
ではreverse系の逆再生の動きの時はイージングも逆になる。animation-direction
の指定はアニメーション開始前には影響がない。animation-play-state
はiOSでの挙動に注意。- @keyframesでは原則、開始点(0%)と終了点(100%)を明示する。
- @keyframesでは、キーフレームごとに
animation-timing-function
の再定義が可能。
※参考記事は、次回の発展編の最後にまとめてご紹介します。