CSSとVue.jsのトランジション
今回はCSSとVue.jsのトランジションについての覚書です。トランジションという言葉を聞きなれない人もいるかもしれません。「スライドメニュー」のアニメーションを想像してください。多くのスライドメニューは画面の端から徐々に広がってくると思います。あの徐々に広がっていく機能を担うのトランジションです。
CSSのトランジションについて勉強したら、何をしているのかよく分からなかったスライドメニューの構造が理解できるようになりました。
Vue.jsではVue.js:「Enter/Leave とトランジション一覧」を参考にその理解を深めていきます。
CSS、Vue.jsともに少し古いブラウザであるIEに関しては考慮していませんのでご容赦ください。
CSSのトランジション
トランジションはVue.jsの独自の機能ではなく、もともとCSSに備わっています。まずはそちらの方を見ていきます。
CSSにおけるトランジションでは次のような項目を設定します。
- transition-property
変化させる対象となるCSSプロパティの名前を設定します。例えば幅と高さ、背景色を変化させたい場合は次のようにします。
transition-property: width height background-color;allとすると変化可能なすべてのプロパティを設定します。逆にnoneとすると何も設定しません。
- transition-duration
変化の始まりから終わりまでの時間の秒数を指定します。10.5秒に設定するには次のようにします。
transition-duration: 10.5s;sの部分をmsとするとミリ秒の設定になります。
- transition-delay
イベントから変化を開始するまでの待ち時間を指定します。指定方法はdurationと同じです。
- transition-timing-function
変化の途中を計算する関数を指定します。この関数によって変化の仕方が変わります。「ease」「linear」「step-end」「steps(n,end)」などが設定できます。
easeは変化の割合が[緩→急→緩]と変わります。linearは常に一定量で変化します。step-endは最初と最後だけ、stepsのnには最後に至るまでの回数を指定します。
これらの項目をまとめて設定する場合は transition: property duration function delay;とすることができ、さらに,(半角コンマ)でつなげることで複数設定が可能です。
また似た設定にtransformというものもあります。変換を意味し、移動したり、伸縮、回転したりします。
例えばtransformにより最終の状態を(90度回転に)設定しして、その変化の過程をtransitionを使って表示させるといった使い方をします。transformはtransitionの中で一つのプロパティとして設定できるので 「transition : transform 2s」とすると「2秒でtransformで指定した最終形にする」という設定になります。
CSS
.box {border-style: solid;
border-width: 1px;
display: block;
width: 30px;
height: 30px;
background-color: #e6b422;
transition: background-color 4s ease .5s, transform 4s ease .5s;
}
.box:hover {
background-color: #e5abbe;
transform: translateX(300px) rotate(1080deg);
}
デモ1はCSSの疑似クラスのhoverを使った。divの上にマウスカーソルが乗ると遷移が始まり、離れると元に戻ります。疑似クラスなら楽ですが、クリックでトランジションを発生させたいとなるとJavaScriptでのコーディングが必要です。element.classlistの.containを使って遷移済みかどうか(遷移後のクラス名を保持しているか)を判別して、遷移前なら.add、そうでなければ.removeで、遷移用のクラスを付与したり削除したりする必要があります。
デモ1(□にマウスカーソルを乗せて下さい)
Vue.jsのトランジション
CSSでクラスの有無によって遷移させるトランジションに似た機能にVue.jsのEnter/Leaveトランジションがあります。(Vue.jsには状態のトランジションというものもありますが、ここでは触れません)
Vue.jsのEnter/Leaveトランジションは、v-ifやv-show、動的コンポーネントに設定できます。設定の仕方は、対象の要素やコンポーネントをtransitionタグで囲むだけです。name属性がなければ、「v-」を、name属性があれば「名前-」を接頭にして状態別に6種のクラスが自動で作成されます。そして作成されたクラスにCSSを記述するだけで切り替えができます。
遷移の契機は、要素やコンポーネントが追加または表示された時と、削除または非表示になった時です。前者はENTER、後者はLEAVEという言葉で表現されます。それらの状態は次の通りです。
- v-enter
このクラスには追加・表示時の遷移の直前の状態を設定します。
- v-enter-active
このクラスには追加や追加・表示時の、遷移(関数や時間)を設定します。
- v-enter-to
このクラスには追加・表示時の遷移が終わった直後の状態を設定します。
- v-leave
このクラスには削除・非表示時の遷移の直前の状態を設定します。
- v-leave-active
このクラスには削除・非表示時の、遷移(関数や時間)を設定します。
- v-leave-to
このクラスには削除・非表示時の遷移が終わった直後の状態を設定します。
これらのクラスの遷移に対して、JavaScriptでフックができる機構も用意されています。これらはtransitionタグ内に記述します。(例: v-on:enter="methodname('param');")
- before-enter
- enter
- after-enter
- enter-cancelled
- leave-enter
- leave
- after-leave
- leave-cancelled
Vue.jsのトランジションのデモ
6つの状態のクラスの反映のされかたを見たり、JavaScriptフックがどこで起きるかを確認したりするためにテストをしてみます。
CSS
.fade-enter-active, .fade-leave-active {transition: all 3s;
}
.fade-enter {
color: red;
}
.fade-enter-to {
color: green;
}
.fade-leave {
color: blue;
}
.fade-leave-to {
color: yellow;
transform: translateX(10px);
}
HTML
<div id="demo"><button v-on:click="show=!show">
開始
</button>
<transition name="fade"
v-on:before-enter="alertStatus('beforeEnter');"
v-on:enter="alertStatus('enter');"
v-on:after-enter="alertStatus('afterEnter');"
v-on:enter-cancelled="alertStatus('enterCancelled');"
v-on:before-leave="alertStatus('beforeLeave');"
v-on:leave="alertStatus('leave');"
v-on:after-leave="alertStatus('afterLeave');"
v-on:leave-cancelled="alertStatus('leaveCancelled');"
>
<p v-if="show">◆◆◆デモ2◆◆◆</p>
</transition>
</div>
SCRIPT
new Vue({el: '#demo',
data: {
show: true
},
methods:{
alertStatus(msg) {
alert(msg);
}
},
})
◆◆◆デモ2◆◆◆
デモ2を実行してみるとfade-leaveの設定値だけが反映されないことに気づきました。調べてみたところなんとなくDOMの再線画と関係があるようですが、詳しいことはわかりませんでした。
他の部分はこれでおよその流れがつかめると思います。v-enter-toの効果は遷移が終わると消えてしまうという所が慣れるまでは扱いにくいところではないでしょうか。同様にv-leave-toの後にもその効果は消えてしまうのですが、v-ifの効果で要素自体が見えなくなってしまっているので違和感はないかもしれません。
よく使うパターンは、初期表示があり、遷移の最終形(削除・非表示直前の形)をv-leave-toとv-enterに同値で設定した上で、途中の遷移をv-leave-active、v-enter-activeに同値で設定するというものだと思います。