Vue.js トランジション&アニメーション

今回では、主にVue.jsのトランジション効果とアニメーション効果について説明します。

移行

Vueは、DOMを挿入、更新、または削除するにはさまざまなトランジション効果を提供します。

Vueは組み込みのトランジションラッパーコンポーネントを提供します。このコンポーネントはトランジション効果を実現するために使用されます。

構文

<transition name = "nameoftransition">
   <div></div>
</transition>

次の例から、Vueのトランジションの過程を解明します。

<div id = "databinding">
<button v-on:click = "show = !show">ここにクリックしてください</button>
<transition name = "fade">
    <p v-show = "show" v-bind:style = "styleobj">アニメーションの例</p>
</transition>
</div>
<script type = "text/javascript">
var vm = new Vue({
el: '#databinding',
    data: {
        show:true,
        styleobj :{
            fontSize:'30px',
            color:'red'
        }
    },
    methods : {
    }
});
</script>

この例では、[ここにクリックしてください]をクリックして、変数showの値をtrueからfalseに変更します。 trueの場合、子要素のpタグの内容を表示します。

次のコードは、transitionタグがpタグをラップすることを示しています。

<transition name = "fade">
    <p v-show = "show" v-bind:style = "styleobj">アニメーションの例</p>
</transition>

トランジションは、実際にはフェードインおよびフェードアウト効果です。 Vueには、要素の表示と非表示には6つのclassがあります。

  • v-enter:enterの開始状態を定義します。要素が挿入される前に有効になり、要素が挿入された後の次のフレームに削除されます。
  • v-enter-active:enterの活性状態を定義します。トランジションフェーズ全体に適用され、要素が挿入される前に追加され、トランジション/アニメーションが終了した後に削除されます。このクラスを使用して、トランジションの開始に対して、期間、遅延、およびイージングカーブを定義できます。
  • v-enter-to:(2.1.8バージョン以降でのみ利用可能です)enterの終了状態を定義します。要素が挿入されると、次のフレームに追加され、(同時にv-enterが削除されます)、トランジション/アニメーションが完了した後に削除されます。
  • v-leave:leaveの開始状態を定義します。 終了状態がトリガーされるとすぐに有効になり、次のフレームが削除されます。
  • v-leave-active:leave の活性状態を定義します。トランジションが終わるフェーズ中に適用されます、leave トランジションがトリガーされるとすぐに有効になり、トランジション/アニメーションが完了した後に削除されます。 このクラスを使用して、トランジションの終了に対して、期間、遅延、およびイージングカーブを定義できます。
  • v-leave-to:(2.1.8バージョン以降でのみ利用可能です)leave の終了状態を定義します。leave トランジションがトリガーされた後、次のフレームに追加され、(同時にv-leaveが削除されます)トランジション/アニメーションが終了した後に削除されます。

これらのトランジションプロセス中に切り替えのクラス名にとっては、要素に名前が付けていない場合、デフォルトでv-がこれらのクラス名の先頭に付きます。を使用する場合、v-enterはmy-transition-enterに置き換えます。

v-enter-activeとv-leave-activeは、トランジションの開始/終了(enter/leave)のさまざまな異なるイージングカーブを指定できます。次には例を挙げます。

CSSトランジション

通常、CSSトランジションを使用します。

次には例を挙げます。

<div id = "databinding">
<button v-on:click = "show = !show">ここにクリックしてください</button>
<transition name="slide-fade">
    <p v-if="show">Florian Studio</p>
</transition>
</div>
<script type = "text/javascript">
new Vue({
    el: '#databinding',
    data: {
        show: true
    }
})
</script>

CSSアニメーション

CSSアニメーションの使い方はCSSトランジションに似ていますが、アニメーションでは、ノードがDOMに挿入された後にv-enterクラス名がすぐに削除されるのではなく、animationendイベントがトリガーされる場合に削除されます。

<div id = "databinding">
<button v-on:click = "show = !show">ここにクリックしてください</button>
<transition name="bounce">
    <p v-if="show">Florian Studio – Tech Power!!!</p>
</transition>
</div>
<script type = "text/javascript">
new Vue({
    el: '#databinding',
    data: {
        show: true
    }
})
</script>

トランジションクラスをカスタマイズする

次の属性で、カスタムトランジションクラスを指定できます

  • enter-class
  • enter-active-class
  • enter-to-class (2.1.8+)
  • leave-class
  • leave-active-class
  • leave-to-class (2.1.8+)

これらは、クラス名の規約を上書きのため、サードパーティのアニメーションライブラリ(animate.cssなど)と組み合わせることができます。

<div id = "databinding">
<button v-on:click = "show = !show">ここにクリックしてください</button>
<transition
    name="custom-classes-transition"
    enter-active-class="animated tada"
    leave-active-class="animated bounceOutRight"
>
    <p v-if="show">Florian Studio – Tech Power!!!</p>
</transition>
</div>
<script type = "text/javascript">
new Vue({
    el: '#databinding',
    data: {
        show: true
    }
})
</script>

トランジションとアニメーションを同時に使用する

Vue はトランジションが終了したことを把握するためのイベントリスナのアタッチを設定する必要があります。要素に適用されるCSSルールに応じて、transitionendまたはanimationendにすることができます。それらのいずれかを使用すると、Vue は自動的に正しいタイプを判断することができます。

しかし、同じ要素に同時に2つのトランジションエフェクトを設定する必要がある場合、例えば、animationがトリガーされてすばやく終了したが、transitionがまだ終わっていません。 この場合、type属性を使用し、animation 或は transitionを設定して、Vue に扱って欲しいタイプを明確に宣言する必要があります。

明示的なトランジション期間の設定

多くの場合、 Vue は、自動的にトランジションが終了したことを見つけ出すことは可能です。 デフォルトでは、Vueはトランジションエフェクトのルート要素の最初のtransitionendまたはanimationendイベントを待ちます。ただし、このように設定しなくても結構です。例えば、一連のトランジション効果のまとまりなどです。幾つかの入れ子となっている内部要素がトランジションのルートのトランジション要素よりは、遅延またはより長いトランジション期間を設けています。

この場合、コンポーネントのdurationプロパティを使用して、明示的な遷移期間(ミリ秒単位)を指定できます。

<transition :duration="1000">...</transition>

活性化時と終了時の期間も指定できます。

<transition :duration="{ enter: 500, leave: 800 }">...</transition>

JavaScriptフック

プロパティでJavaScriptフックを宣言できます。

HTML コード:

<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" >
 <!-- ... --> 
</transition>

JavaScript コード:

// ... 
methods: { 
// -------- 
// 進入中 
// -------- 
beforeEnter: function (el) { 
// ... 
}, 
// コールバック関数(オプション) 
// CSSと組み合わせて使用する 
enter: function (el, done) { 
// ... 
done() 
}, 
afterEnter: function (el) { 
// ... 
}, 
enterCancelled: function (el) { 
// ... 
}, 
// -------- 
// 終了 
// -------- 
beforeLeave: function (el) { 
// ... 
}, 
// コールバック関数(オプション) 
// CSSと組み合わせて使用する 
leave: function (el, done) { 
// ... 
done() 
}, 
afterLeave: function (el) {
 // ... 
}, 
// leaveCancelled はv-show のみと共に使用する
leaveCancelled: function (el) {
 // ... 
}
}

これらのフック関数は、CSS transitions/animationsと組み合わせて使用できるし、個別にも使用できます。

JavaScriptのみでトランジションの場合、EnterおよびLeaveのコールバックにdoneを使用する必要があります。それ以外の場合、同期的に呼び出され、トランジションはすぐに終了します。

トランジションにJavaScriptのみを使用する要素にv-bind:css=”false”を追加することをお勧めします。VueはCSS判定をスキップします。これより、誤って CSS ルールがトランジションに干渉することを防ぎます。

Velocity.jsを使用する簡単な実例

<div id = "databinding">
<button v-on:click = "show = !show">ここにクリックしてください</button>
<transition
    v-on:before-enter="beforeEnter"
    v-on:enter="enter"
    v-on:leave="leave"
    v-bind:css="false"
  >
    <p v-if="show">Florian – Tech Power!!!</p>
</transition>
</div>
<script type = "text/javascript">
new Vue({
  el: '#databinding',
  data: {
    show: false
  },
  methods: {
    beforeEnter: function (el) {
      el.style.opacity = 0
      el.style.transformOrigin = 'left'
    },
    enter: function (el, done) {
      Velocity(el, { opacity: 1, fontSize: '1.4em' }, { duration: 300 })
      Velocity(el, { fontSize: '1em' }, { complete: done })
    },
    leave: function (el, done) {
      Velocity(el, { translateX: '15px', rotateZ: '50deg' }, { duration: 600 })
      Velocity(el, { rotateZ: '100deg' }, { loop: 2 })
      Velocity(el, {
        rotateZ: '45deg',
        translateY: '30px',
        translateX: '30px',
        opacity: 0
      }, { complete: done })
    }
  }
})
</script>

初期描画時のトランジション

appearプロパティを使用して、初期描画時にノードのトランジションを設定できます。

<transition appear>
  <!-- ... -->
</transition>

デフォルトではentering と leavingトランジションと同じであり、CSSクラス名もカスタマイズできます。

<transition
  appear
  appear-class="custom-appear-class"
  appear-to-class="custom-appear-to-class" (2.1.8+)
  appear-active-class="custom-appear-active-class"
>
  <!-- ... -->
</transition>

カスタムJavaScriptフック

<transition
  appear
  v-on:before-appear="customBeforeAppearHook"
  v-on:appear="customAppearHook"
  v-on:after-appear="customAfterAppearHook"
  v-on:appear-cancelled="customAppearCancelledHook"
>
  <!-- ... -->
</transition>

要素間のトランジション

要素間のトランジションについて説明します。

同じタグ名の要素を切り替える場合は、key属性を使用して唯一の値を設定し、Vueがそれらを区別できるようにする必要があります。そうしないと、Vueは効率化のために同じタグ内の内容のみを置き換えます。

<transition>
  <table v-if="items.length > 0">
    <!-- ... -->
  </table>
  <p v-else>申し訳ありませんが、お探しの内容が見つかりませんでした。</p>
</transition>

<transition>
  <button v-if="isEditing" key="save">
    Save
  </button>
  <button v-else key="edit">
    Edit
  </button>
</transition>

このケースでは、 key 属性を同一要素の異なる状態のトランジションのために使えます。v-if と v-else を使う代わりに、次のように書きかえることができます:

<transition>
  <button v-bind:key="isEditing">
    {{ isEditing ? 'Save' : 'Edit' }}
  </button>
</transition>

複数のv-ifを使用した複数の要素のトランジションは、動的プロパティがバインドされた単一の要素のトランジションとして書き直せます。例えば:

<transition>
  <button v-if="docState === 'saved'" key="saved">
    Edit
  </button>
  <button v-if="docState === 'edited'" key="edited">
    Save
  </button>
  <button v-if="docState === 'editing'" key="editing">
    Cancel
  </button>
</transition>

下記に書き直せます。

<transition>
  <button v-bind:key="docState">
    {{ buttonMessage }}
  </button>
</transition>

// ...
computed: {
  buttonMessage: function () {
    switch (this.docState) {
      case 'saved': return 'Edit'
      case 'edited': return 'Save'
      case 'editing': return 'Cancel'
    }
  }
}
Share

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です