CSSアニメーションを使いこなすために知っておきたい5つのこと

# はじめに

keyframesを使ったCSSアニメーションは描画パフォーマンスが良く、ヌルヌルな動きが簡単に実装できます。
最近旧IEのサポートが切られたこともあり、今後は触る機会もより増えてくるかと思います。

そこでCSSアニメーションをガリガリ使っていく上で、これは覚えておきたい！と思ったことをまとめてみました。何かの参考にでもなれば幸いです。

- 基本的なプロパティや使い方などは省略します
- サンプルコードではprefixを省略しています
- 5つとは単に私が思いついた数なので、深い意味はありません





# 目次

- はじめに
- 複雑なイージングはChrome Devtoolsで簡単に実装できる
- イージングはkeyframesの中で細かく再定義できる
- カンマ区切りでシーケンシャルに表現する
- コマ送りアニメーションにはsteps()が便利
- アニメーションのcallback（イベント）を取得する
- 終わりに





# 複雑なイージングはChrome Devtoolsで簡単に実装できる

デフォルトで用意されているイージングの値は、ease, linear, ease-in, ease-out, ease-in-outなど多くはありません。jQueryプラグインなどで用意されているような複雑なイージングはcubic-bezier()を使えば実現可能ですが、3次ベジェ曲線なので調整が大変です。

そこでChrome Devtoolsの機能を使えば、直感的にcubic-bezier()を生成することができます。
（生成してくれるプリプロセッサやオンラインサービスもあります）

> Devtoolsを使ったcubic-bezier()生成については、過去投稿した記事で簡単に説明しています。詳細は以下をご覧ください。
> [知っていると幸せになれるかもしれないChromeDevtoolsの小技集 ～CSS開発編～　#イージングの簡単設定](http://qiita.com/nekoneko-wanwan/items/de7553ea9c3eb30cd87d#%E3%82%A4%E3%83%BC%E3%82%B8%E3%83%B3%E3%82%B0%E3%81%AE%E7%B0%A1%E5%8D%98%E8%A8%AD%E5%AE%9A)





# イージングはkeyframesの中で細かく再定義できる

イージングは`animation-timing-function`を使って定義しますが、このプロパティはkeyframesの中で再定義が可能です。上手く使えばシンプルなコードで複雑なアニメーションが実装できます。


```keyframeの中でイージングを再定義.css
div {
  background-color: red;
  height: 20px;
  width: 20px;
  animation: 'bounce' 2s ease-out 0s infinite alternate;
}

@keyframes bounce {
  from {
    margin-top: 100px;
    animation-timing-function: ease-out;
  }
  25% {
    margin-top: 50px;
    animation-timing-function: ease-in;
  }
  50% {
    margin-top: 100px;
    animation-timing-function: ease-out;
  }
  75% {
    margin-top: 75px;
    animation-timing-function: ease-in;
  }
  to {
    margin-top: 100px;
  }
}
```

**[動作イメージ]**
![anim1.gif](https://qiita-image-store.s3.amazonaws.com/0/58436/842d03f4-b38c-d47f-85e0-befe2a3fb19b.gif)




# カンマ区切りでシーケンシャルに表現する

複数のアニメーションを自由に組み合わせたい！
決まった順番にアニメーションを実行したい！

アニメーションのイベントはjavaScriptで取得できるため、jsと組み合わせて実装することが多いかと思います。
が、単純なものであれば**カンマ区切りとanimation-fill-mode**を使ってCSSだけでも表現可能です。

```シーケンシャルなアニメーション.css
div {
  background-color: red;
  height: 20px;
  width: 20px;
  animation:
    'h' 1s ease 0s alternate forwards,
    'w' 1s ease 1s alternate forwards,
    'h' 1s ease 2s reverse forwards,
    'w' 1s ease 3s reverse forwards;
}

@keyframes h {
  from { height: 20px;}
  to   { height: 100px;}
}
@keyframes w {
  from { width: 20px;}
  to   { width: 100px;}
}
```

**[動作イメージ]**
![anim2.gif](https://qiita-image-store.s3.amazonaws.com/0/58436/2330ff7d-6daf-9418-e211-bed0baba0f4e.gif)



## ポイント

- animationの値をカンマ区切りで並べることで、複数のアニメーションを同時に設定しています
- `animation-fill-mode: forwards;` を指定することで、直前に設定した値を引き継いで次のアニメーションの実行ができます
- `animation-delay: ;`で各アニメーションの発動タイミングをずらし、あたかも順番を守っているかのように見せることができます

> delayの値を調整することで「これとこれは同時に実行して」「これはその後に実行する」といった多少複雑なことも可能です。またkeyframesの粒度を小さくすることもできるので、コードをシンプルにできるかもしれません。（prefixも考えると出力コードは増えそうですが）





# コマ送りアニメーションにはsteps()が便利

CSS transitionであればプロパティを指定することで、アニメーションさせたいプロパティを制限することができます。しかしkeyframesは基本的に動かせるものは全てアニメーションしてしまいます。コマ送りやパラパラと切り替えたい場合には、animation-timing-functionの**steps()**が便利です。

```stepsを使ったコマ送りアニメーション.css
div {
  background-color: red;
  height: 20px;
  width: 20px;
  animation: 'parapara' 0.5s steps(2, start) 0s infinite alternate;
}

@keyframes parapara {
  from { height: 20px;}
  to   { height: 50px;}
}
```

**[動作イメージ]**
![anim3.gif](https://qiita-image-store.s3.amazonaws.com/0/58436/80ba05aa-26bf-0d26-ea2f-123d263efb7c.gif)



> steps()については、過去投稿した記事で簡単に説明しています。詳細は以下をご覧ください。
> [はじめよう！スプライトアニメーション　#cssだけで表現してみる](http://qiita.com/nekoneko-wanwan/items/b0e64404a5cff582247a#css%E3%81%A0%E3%81%91%E3%81%A7%E8%A1%A8%E7%8F%BE%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B)



## アニメーションできない指定を使う

スプライトのようにbackground-positionで値を操作するのではなく、画像自体を差し替えてしまえばsteps()を使わずともコマ送りを実現させることができます（というか動かせない）。

```画像を差し替えてコマ送りアニメーション.css
div {
  height: 16px;
  width: 16px;
  animation: 'switchIcon' 1s ease 0s infinite;
}

@keyframes switchIcon {
  from {
    /* アイコン画像1 */
    content: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAArUlEQVQ4T8WTIQ6DQBBFHw6JxMFRkD1GZWUdskUicZUcoUfoUYqrrEQ2P5lNtruFbAVh1CQ78+f/+TsZy1ECR+AA3IEReIfl2QqAnq7ABegsj8o3BZAETT8BN2PxSpWg5taac2A2kB74AlmScLbphTdRC9ROBp/FL4DamuVAGHJCC326h00BGmDyKFTA4x8GapZmF8oFkixhfwBR19ZdOFeSJexno38D4UeKbuID1HczERkBWZYAAAAASUVORK5CYII=');
  }
  to {
    /* アイコン画像2 */
    content: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABEklEQVQ4T63TLzPEURTG8c8mokb0ChBFTWQUfwqNRqMZjegd0GiGItIohiZSDE1ciXl2zu6sHWOM3VPu/H73nu99znPObegzGn3mGxhguJQ0a833JKYxgidc1/pNdBTkwDrGcIhAtrGBNjhJj9jHKeYxk58BrGEO7wVYxBZucIEXTGAZr9iryzqAo5J7j1usFuwZsxjHGd7qohN81LmWgiSO4hJJCuCuCl3o8uaqSoqKB0RpM4DPOhQlvwFi4lCVcVyAloLUG6kh/7WEADbbJsaMyE6kC0u1GRPPu0xc6TIxHdn9CRCH08adam1vGw8QE9PyDiBzkIFJxKgAkjjVM0jZy0Alst9pY1/PYWBv4d8qvgBJr0W7oeYU2wAAAABJRU5ErkJggg==');
 }
}
```

**[動作イメージ]**
![anim4.gif](https://qiita-image-store.s3.amazonaws.com/0/58436/7da04b0e-a5b8-902f-a4d5-5524919d93a4.gif)



> **[補足]**
colorをsteps()で制御する場合、途中の色が適用されてしまうのか指定した色を正しく表現してくれません。ちょっと回避策が思いつかなかったので、steps()で色の変更を行う際はご注意ください。※対応策があればご教授ください。
 
> ```色が正しくでないコマ送りアニメーション.css
div {
  height: 20px;
  width: 20px;
  animation: 'switchColor' 0.5s steps(2, start) infinite alternate;
}
@keyframes switchColor {
  from { background-color: blue;}
  to   { background-color: red;}
}
```

>**[動作イメージ]**
![anim5.gif](https://qiita-image-store.s3.amazonaws.com/0/58436/a20daa30-dcba-376d-c2a9-8347385ef303.gif)
※blueが紫になってしまっている




# アニメーションのcallback（イベント）を取得する

すでに触れていますが、javaScriptによってアニメーションのイベントを取得することができます。

- animationstart（delay完了後）
- animationend（終了後）
- animationiteration（反復が終わる時）

> 具体的なコードは以下ページを紹介させていただきます
> [CSS3アニメーションのイベントを取得する](http://qiita.com/omatoro/items/0388b90a104568093691)




# 終わりに

## 自作の関連ページ

- [知っていると幸せになれるかもしれないChromeDevtoolsの小技集 ～CSS開発編～　#イージングの簡単設定](http://qiita.com/nekoneko-wanwan/items/de7553ea9c3eb30cd87d#%E3%82%A4%E3%83%BC%E3%82%B8%E3%83%B3%E3%82%B0%E3%81%AE%E7%B0%A1%E5%8D%98%E8%A8%AD%E5%AE%9A)
- [はじめよう！スプライトアニメーション　#cssだけで表現してみる](http://qiita.com/nekoneko-wanwan/items/b0e64404a5cff582247a#css%E3%81%A0%E3%81%91%E3%81%A7%E8%A1%A8%E7%8F%BE%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B)


## 参考サイト一覧

- [CSS3アニメーションのイベントを取得する](http://qiita.com/omatoro/items/0388b90a104568093691)
- [CSS Animations Level 1 日本語訳](http://www.hcn.zaq.ne.jp/___/WEB/css-animations-ja.html)