これだけ覚える CSS3 アニメーション + Vue.jsで楽をする


![9g98XcumrH.gif](https://qiita-image-store.s3.amazonaws.com/0/32596/5271093c-c7cc-a9a2-2528-e06348355098.gif "9g98XcumrH.gif")


CSS3アニメーション、なるべく覚えたくないですし、誰かによしなにやってほしいですね。でもかっこいい画面は作りたい。

というわけで最低限だけ説明します。某所で行ったLTの内容をベースにしておりますので、さらに面倒な方はスライドを流し読みしてください。（ただし、スライドの方は不正確な部分がありますので、時間があれば当記事で補完していただけるといいかと思います。）

スライドは以下です。

https://speakerdeck.com/hashrock/koredakejue-eru-css3-animesiyon

[DEMOはこちら](http://hashrock-sandbox.github.io/vuejs-transition-example/)


# 対象

 * CSS3アニメーション、基本的にコピペで実装するし、なるべくなら一生知らずにいたい方
 * かといって、CSSフレームワークに頼ると大量のCSSに埋もれるのが辛い人
 * だからといってjQueryに頼るのも嫌な人

# 今回説明すること

 * CSS3 Animationの最低限の書き方
 * 基本的なイージングの種類
 * Vue.jsでアニメーションの省力化
 * アニメーションタイミングをずらす方法
 * 3Dっぽい動きを付ける方法
 * ベンダプレフィックスを手で書かないために

# 説明しないこと

 * キーフレームを使ったアニメーション
 * パフォーマンス絡みの説明（layoutなど）

# CSS3アニメーション（Transition）の書き方

いろいろ書き方がありますが、最低限のものは下記の通りです。

![スクリーンショット 2015-06-17 0.38.35.png](https://qiita-image-store.s3.amazonaws.com/0/32596/ad57f6ac-9cbb-e2f5-c089-bb140e2d7221.png "スクリーンショット 2015-06-17 0.38.35.png")


一つ目の引数は、どのプロパティを変化させるかを表します。`all`と指定すると、全パラメータが対象になりますので、最初はallを指定しておけばいいでしょう。（もちろん`all`と指定した場合はパフォーマンス的に劣ることにはなります）

二つ目の引数は、変化スピードです。この例だと、1秒かけてアニメーションしていくことになります。その２倍のスピードで変化させたい場合は、0.5sと指定すればいいわけです。

三つ目の引数は、変化カーブ（timing function）です。「はじめはゆっくり、あとは素早く」といったように、トランジションの速度を変化させることができます。

指定可能な値に、`ease`, `ease-in`, `ease-out`, `ease-in-out`などがありますが、最もよく使うのはやや早く立ち上がり、ゆっくりと静止する `ease` でしょう。`ease-in-out` を使うと、似た動きですが、よりゆったりした動き出しになります。

[Ceaser](http://matthewlein.com/ceaser/
)というWebサイト上で、下記のように動きを確かめることができます。また、ベジェ曲線で自分なりのtiming functionをデザインすることもできます。

![c2KS6lDlE9.gif](https://qiita-image-store.s3.amazonaws.com/0/32596/3b45681e-2572-f211-1d26-7f3a0f8b50f3.gif "c2KS6lDlE9.gif")

![0HJuCAnX4C.gif](https://qiita-image-store.s3.amazonaws.com/0/32596/4a0215a7-a8f3-7761-e3d8-b1b467506927.gif "0HJuCAnX4C.gif")


なお、この記法は省略記法です。３つの引数はそれぞれ、`transition-property`、`transition-duration`、`timing function`にあたります。

# ホバーすると色が変わるリンクの例

表題のようなものは、例えば下記のように書きます。

![スクリーンショット 2015-06-17 1.11.52.png](https://qiita-image-store.s3.amazonaws.com/0/32596/b5568b12-f36c-8a2d-aed4-f129b3f4673d.png "スクリーンショット 2015-06-17 1.11.52.png")

`a`セレクタで指定したプロパティから、`a:hover`セレクタで指定したプロパティへ、スムーズに変化します。

[動作デモ](http://hashrock-sandbox.github.io/vuejs-transition-example/index3.html)



# TransitionをVue.jsで簡単に指定する

[Vue.js](http://vuejs.org/)には、このようなアニメーションを簡単に要素に適用するための機能があります。

トランジション機能を適用するには、対象要素に`v-transition`を追記します。

```html
<div class="card" v-repeat="card : cards" v-transition>
	<h2>{{card.name}}</h2>Lorem ipsum dolor sit amet
</div>
```

すると、要素に `v-transition` というクラスが適用されるとともに、生成時に `v-enter`、削除時に `v-leave` というクラスが適用されます。

```css
.v-transition {
	transition: all 0.7s ease;
	transform: scale3d(1, 1, 1);
}
.v-enter, .v-leave {
	transform: scale3d(0, 0, 1);
	opacity: 0;
}
```

たったこれだけのコードで、下のGIFのように、Vue.jsがよしなにしてくれます。

![8azrWpajRg.gif](https://qiita-image-store.s3.amazonaws.com/0/32596/4b99930b-81ce-8b14-60cf-baf4c246e120.gif "8azrWpajRg.gif")

[動作デモ](http://hashrock-sandbox.github.io/vuejs-transition-example/index.html)


DOMを動かそうと考える時、とにかく状態をJS側に持たせてしまいがちですが、「生成時、削除時」の２つのタイミングでCSSクラスを当てることで、ロジック内の状態を減らすことができます（下図）。

![スクリーンショット 2015-06-17 1.24.03.png](https://qiita-image-store.s3.amazonaws.com/0/32596/3ab72da3-c992-419b-60ad-6999b090841f.png "スクリーンショット 2015-06-17 1.24.03.png")

Vue.jsはこのような処理を自動で行ってくれるので、結果的にロジックからアニメーション関連のコードを削減することができます。

# 表示タイミングをずらす

要素の表示タイミングをずらすことで、よりアニメーションを印象的にすることができます。

Vue.jsの最新バージョン（0.12.x）で、このようなアニメーションの支援機能(`stagger`)が追加されました（angularにも同様の機能があるようです）。

先ほどのコードに `stagger="70"` と追記するだけで、下記のように、タイミングを70msずつずらしながら要素を一つずつ表示するようになります。詳しい使い方は[Staggering Transitions](http://vuejs.org/guide/transitions.html#Staggering_Transitions)を参照してください。

```html
<div class="card" v-repeat="card : cards" v-transition stagger="70">
	<h2>{{card.name}}</h2>Lorem ipsum dolor sit amet
</div>
```

![C68BX3FAZF.gif](https://qiita-image-store.s3.amazonaws.com/0/32596/e0e284ec-69ee-d869-9c91-eec11cb1d2d9.gif "C68BX3FAZF.gif")

[動作デモ](http://hashrock-sandbox.github.io/vuejs-transition-example/index1.html)


# 3D風の動きを付ける

`matrix3d` プロパティを利用することで、奥行きのあるアニメーションを作ることができます。

```css
.v-transition {
	transition: all 0.7s ease;
	transform-origin: center top 0px; 
}

.v-enter, .v-leave {
	transform: matrix3d(1,0,0.00,0,0.00,0,1.00,0.008,0,-1,0,0,0,0,0,1);
	opacity: 0;
}
```

![9g98XcumrH.gif](https://qiita-image-store.s3.amazonaws.com/0/32596/5271093c-c7cc-a9a2-2528-e06348355098.gif "9g98XcumrH.gif")

[動作デモ](http://hashrock-sandbox.github.io/vuejs-transition-example/index2.html)


`matrix3d`は変換に使う行列、`transform-origin`は変形の原点を指定しています。

しかし、matrix3dに指定する行列を手書きするのはやや厳しいです。

そんな時、[CSS generator | transform: matrix3d](http://ds-overdesign.com/transform/matrix3d.html)を使うのがオススメです。パラメータをグラフィカルに生成することができます。


# ベンダプレフィックス

例えば、アニメーションによく用いられる`transforms3d`の対応状況は、下記URLから見られます。

http://caniuse.com/#feat=transforms3d

2015/06/17現在、iOS Safariでベンダプレフィックス（-webkit-）が必要、IEが部分的サポートなど、まだまだフル対応とは言えません。

CSS3 Animationを使う以上、`autoprefixer`などの自動プレフィックス付加ツールを使いましょう。余計なプレフィックスも除去してくれますし、ベンダプレフィックスは人の手で管理できる範疇を超えています。

また、`Stylus + nib`の組み合わせでも、ベンダプレフィックスの補完を行ってくれるようです。

# 終わりに

CSS3には、同じようなことができる`Transition`と`Animation`の二つの仕様があります。今回は簡易な`Transition`のみを説明しました。

アニメーションは視線を奪ってしまうため、本来控えめに使うべきものだと考えています。ボックスの回転やバウンドなどもCSSアニメーションで行えますが、ユーザのUI理解の助けにならないアニメーションの採用にはもっと慎重になるべきではないかと思っています。

より意義のあるアニメーションの使い方は、[Material Design](http://www.google.com/design/spec/animation/meaningful-transitions.html#)などが参考になるでしょう。

# GitHub

https://github.com/hashrock-sandbox/vuejs-transition-example

# 参考サイト

 * http://tympanus.net/codrops/2013/02/08/designing-with-motion/
 * http://tympanus.net/codrops/2013/05/07/a-collection-of-page-transitions/
 * http://tympanus.net/codrops/2014/12/08/inspiration-dialog-effects/
 * http://www.slideshare.net/amberweinberg/practical-css3-animations