Vue.jsには、要素の表示・非表示の挙動においてアニメーションを実装していくtransition(トランジション)と呼ばれる機能があります。本記事ではフェードイン・フェードアウトを実装することによって、基本的なアニメーションの実装の流れを説明していきます。
基本的なtransitionの実装手順
まずは基本的なフェードイン・フェードアウトの実装から、実装手順を説明します。
サンプル1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.6/dist/vue.js"></script> <style> .v-enter-active, .v-leave-active { transition: opacity 3s ease-out; } .v-enter, .v-leave-to { opacity: 0; } </style> </head> <body> <div id="app"> <button @click="toggleBtn">表示/非表示ボタン</button> <transition> <p v-show="show">本日は晴天なり</p> </transition> </div> <script> new Vue({ el: '#app', data: { show: false }, methods: { toggleBtn: function () { this.show = !this.show } } }); </script> </body> </html> |
1. transitionタグで囲む
まずトランジションを適用したい範囲をtransitionタグで囲み、transitionコンポーネントを作成します(23〜25行目)。このコンポーネント内の要素に対して、アニメーションなどの動きをCSSで記述していくためのクラスが自動的に付与されます。
2. v-show/v-ifディレクティブの適用
実際に付与されるクラス(CSS)によって動きを制御したい要素には、v-showまたはv-ifディレクティブで表示・非表示する挙動を実装する必要があります(24行目)。このディレクティブの機能によってクラスを切り替えていく機能が自動で割り当てられます
3. クラス(CSS)を記述する
付与されるクラスは大まかに「Enterフェーズ」と「Leaveフェーズ」の2つに分類されます。この2つのフェーズは、v-showおよびv-ifディレクティブの機能によって切り替わっていくように処理されます。サンプル1ではボタンをクリックするとちょうど下記のイラストの流れ(左から右)でクラスが適用されていきます。
はじめは.v-enterで文字はopacityがゼロの透明状態です。ボタンを1回クリックすると.v-enter-activeの処理が走り(3秒間)、そして.v-enter-toとなり文字が表示されます。ボタンをもう1回クリックすると.v-leave-active、そして.v-leave-toへと至ります。
.v-enter-toと.v-leaveはデフォルトでopacity: 1なので、CSSとしてのスタイルには記述していません。
上記のイラストをまとめた表です。
クラス名 | タイミング |
.v-enter | Enter開始(要素が追加される前) |
.v-enter-active | Enter開始後に実行されている間 (要素が追加されている間) |
.v-enter-to | Enter完了(要素が追加された時) |
.v-leave | Leave開始(要素が削除される前) |
.v-leave-active | Leave開始後に実行されている間 (要素が削除されている間) |
.v-leave-to | Leave完了(要素が削除された時) |
クラス名のプレフィックス(transitionの区別)
サンプル1では1つのtransition(コンポーネント)のみでしたが、複数のtransitionを区別して利用するには、タグに例えば「name=”hoge”」というようにname属性を付加します。これによって、hogeをプレフィックスとしたクラスが生成されるようになります。
サンプル2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.6/dist/vue.js"></script> <style> .v-enter-active, .v-leave-active { transition: opacity 3s; } .v-enter, .v-leave-to { opacity: 0; } .rain-enter-active, .rain-leave-active { transition: opacity 1s; } .rain-enter, .rain-leave-to { opacity: 0; } </style> </head> <body> <div id="app"> <button @click="toggleBtn">表示/非表示ボタン</button> <transition> <p v-show="show">本日は晴天なり</p> </transition> <transition name="rain"> <p v-show="show">本日は雨天なり</p> </transition> </div> <script> new Vue({ el: '#app', data: { show: false }, methods: { toggleBtn: function () { this.show = !this.show } } }); </script> </body> </html> |
36行目
name属性にrainを記述しています。このrainがクラス名のプレフィックスとなり、例えば「.rain-enter-active」のように記述してデフォルトの「.v-enter-active」と区別することができます。
サンプル1と2共にボタンをクリックすることによるv-showの切り替えによってtransitionによる動きが確認されましたが、transitionタグにappear属性を付与すると、ページがはじめに表示される(DOMが描画される)段階でtransitionが実行されるようになります。
サンプル3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.6/dist/vue.js"></script> <style> .v-enter-active, .v-leave-active { transition: 2s ease-out; } .v-enter, .v-leave-to { opacity: 0; transform: translateY(50px) } </style> </head> <body> <div id="app"> <button @click="toggleBtn">表示/非表示ボタン</button> <transition appear> <p v-show="show">本日は晴天なり</p> </transition> </div> <script> new Vue({ el: '#app', data: { show: true }, methods: { toggleBtn: function () { this.show = !this.show } } }); </script> </body> </html> |
カスタムトランジションクラス(Custom Transition Classes)
上述してきたtransitionでは .v-enter や .v-enter-active のように自動的に生成されるクラス名を利用してきましたが、Animate.cssなどのライブラリ等を利用する際に、カスタマイズされたクラス名を割り当てたい場合があります。その際に利用するのが、「カスタムトランジションクラス」です。
例えば下記コードはサンプル1と全く同じ挙動をしますが、本来自動的に割り当てられる .v-enter-activeと.v-leave-active というクラス名を、それぞれ myEnterClass、myLeaveClass という名前に置き換えています。
サンプル4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.6/dist/vue.js"></script> <style> .myEnterClass, .myLeaveClass { transition: 2s ease-out; } .v-enter, .v-leave-to { opacity: 0; transform: translateY(50px) } </style> </head> <body> <div id="app"> <button @click="toggleBtn">表示/非表示ボタン</button> <transition enter-active-class="myEnterClass" leave-active-class="myLeaveClass"> <p v-show="show">本日は晴天なり</p> </transition> </div> <script> new Vue({ el: '#app', data: { show: false }, methods: { toggleBtn: function () { this.show = !this.show } } }); </script> </body> </html> |
24行目
.v-enter-activeと.v-leave-activeは、それぞれtransitionの属性に「enter-active-class」「leave-active-class」というプロパティを用意し適当な名前のクラス名(上記ではmyEnterClass、myLeaveClass)を割り当てています。
EnterフェーズおよびLeaveフェーズにおける各動作に対するプロパティは下記表の通りです。
プロパティ名 | タイミング |
enter-class | Enter開始 |
enter-active-class | Enger開始後に実行されている間 |
enter-to-class | Enter完了 |
leave-class | Leave開始 |
leave-active-class | Leave開始後に実行されている間 |
leave-to-class | Leave完了 |
下記コードでは、実際にAnimate.cssライブラリを利用しています。
サンプル5
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.6/dist/vue.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css"> </head> <body> <div id="app"> <button @click="toggleBtn">表示/非表示ボタン</button> <transition appear enter-active-class="animated bounceIn" leave-active-class="animated bounceOut"> <p v-show="show">本日は晴天なり</p> </transition> </div> <script> new Vue({ el: '#app', data: { show: true }, methods: { toggleBtn: function () { this.show = !this.show } } }); </script> </body> </html> |
JavaScriptフックについて
EnterフェーズおよびLeaveフェーズの過程において、イベント(関数)を実行したい場合があります。transitionでは下記表のように各フェーズのポイント(いわゆるフック)において、イベントを実行することができます。この機能を駆使しJavaScriptを利用していくことによってより複雑なアニメーションを実装していくことが可能となります。
イベント名(フック) | タイミング |
before-enter | Enter開始直前 |
enter | Enter開始 |
after-enter | Enter完了 |
enter-cancelled | Enterキャンセル |
before-leave | Leave開始前 |
leave | Leave開始 |
after-leave | Leave完了 |
leave-cancelled | Leaveキャンセル |
実際に各イベントが発生するタイミングにおいて、コンソールで文字を出力しているのがサンプル6です。
サンプル6
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.6/dist/vue.js"></script> <style> .v-enter-active, .v-leave-active { transition: opacity 3s ease-out; } .v-enter, .v-leave-to { opacity: 0; } </style> </head> <body> <div id="app"> <button @click="toggleBtn">表示/非表示ボタン</button> <transition v-on:before-enter="beforeEnter" v-on:enter="enter" v-on:after-enter="afterEnter" v-on:enter-cancelled="enterCancelled" v-on:before-leave="beforeLeave" v-on:leave="leave" v-on:after-leave="afterLeave" v-on:leave-cancelled="leaveCancelled"> <p v-show="show">本日は晴天なり</p> </transition> </div> <script> new Vue({ el: '#app', data: { show: false }, methods: { toggleBtn: function () { this.show = !this.show }, beforeEnter: function () { console.log('before-enter') }, enter: function () { console.log('enter') }, afterEnter: function () { console.log('after-enter') }, enterCancelled: function () { console.log('enter-cancelled') }, beforeLeave: function () { console.log('before-leave') }, leave: function () { console.log('leave') }, afterLeave: function () { console.log('after-leave') }, leaveCancelled: function () { console.log('leave-cancelled') } } }); </script> </body> </html> |
transitionタグにv-onディレクティブでイベント名とハンドラを指定しています。実際にブラウザのコンソール画面を開いてみると、ボタンをクリックするごとにそれぞれのイベントが発生していることを確認できます。例えば1回目にボタンをクリックすると3秒後にEnterフェーズが完了となり(要素が追加された時) afterEnter と出力されるのが確認できます。
animationによるキーフレーム
animationを利用すると、キーフレームによるアニメーションを実装することができます。
サンプル7
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.6/dist/vue.js"></script> <style> .v-enter-active { animation: bounce 10s; } .v-leave-active { animation: bounce 10s reverse; } @keyframes bounce { 0% {transform: scale(0);} 50% {transform: scale(1.5);} 100% {transform: scale(1);} } </style> </head> <body> <div id="app"> <button @click="toggleBtn">表示/非表示ボタン</button> <transition> <p v-show="show" style="width:150px;height:150px;background-color:green">本日は晴天なり</p> </transition> </div> <script> new Vue({ el: '#app', data: { show: true }, methods: { toggleBtn: function () { this.show = !this.show } } }); </script> </body> </html> |
8〜10行目
Enterフェーズ実行中におけるキーフレーム名と実行時間を指定しています。bounceという適当に付けたキーフレーム名を指定し、実際のアニメーションは16〜20行目の@keyframes〜で記述しています。
12〜14行目
Leaveフェーズ実行中においては、reverse の指定により、16〜20行目の@keyframes〜で記述したアニメーションの逆再生を実行しています。
16〜20行目
EnterおよびLeaveフェーズで指定したbounceという名前のキーフレームを記述しています。どちらのフェーズも10秒間に指定しているので、50%のキーの部分、つまりボタンをクリックして5秒後が一番スケール(scale)の大きくなるアニメーションとして実行されます。