Vue3でGSAPを使ってページ遷移時のアニメーションを実装する


初投稿です。間違いなどあれば指摘いただけると幸いです。

概要

Vue3でページ遷移時のアニメーションをアニメーションライブラリであるGSAPを使って実装する方法です。

Vueには標準で transition という機能がありますが、ページ遷移時のアニメーションの場合新しいページのレンダリング状況を確認する必要があるため、そのままでは実装できません。専用のライブラリを導入するなどの方法もありますが、今回はGSAPを使って実装する方法を紹介します。

環境

以下の環境での動作を確認しています。GSAPの導入がまだの方は npm install gsap からインストールしてください。また、Vue Routerによるルーティングの設定は済んでいるものとします。TypeScriptはどちらでも構いません。

  • Vue 3.2.29
  • Vue Router 4.0.12
  • GSAP 3.9.1
  • TypeScript 4.5.5

実装

ページが切り替わったときにアニメーションを適用させたい要素にCSSのclassを当ててください。

今回は App.vue<RouterView /> に対して適用させるため、divで囲って .wrapper というclassを当てました。

App.vue
<script setup lang="ts">
import { RouterLink, RouterView } from 'vue-router';
</script>

<template>
  <RouterLink to="/">
    <header>
      <img src="@/assets/logo.svg" />
      <h1>Site Title</h1>
    </header>
  </RouterLink>
  <div class="wrapper">
    <RouterView />
  </div>
</template>

Vue Routerによるルーティングを設定しているファイル ( router/index.ts など ) に、以下のコードを追記してください。

router/index.ts
import { createRouter, createWebHistory, type RouterScrollBehavior } from 'vue-router';
import gsap from 'gsap';

import HomeView from '@/views/HomeView.vue';


const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  // routesの中身はご自分の環境に合わせ適宜修正してください
  routes: [
    {
      path: '/',
      component: HomeView
    }
  ]
});

// ここから

router.beforeEach((to, from, next) => {
  const tl = gsap.timeline();
  tl.to(".wrapper", {
    duration: 0.5,
    opacity: 0,
    onComplete: () => {
      next();
    }
  }).to(".wrapper", {
    duration: 0.5,
    opacity: 1
  }, 1);
});

// ここまで

export default router;

今回はページ遷移開始直前に .wrapper の透明度を0.5秒かけて0にした後、ページ遷移を実行し、完了後0.5秒かけて透明度を0に戻すというアニメーションを実装しました。

GSAPの timeline() は複数のアニメーションを連結させることができる「タイムライン」を作るメソッドです。また .to() 内の onComplete は対象のアニメーションが完了した後に呼び出される関数です。

2つ目の .to() の第3引数で 1 を指定していますが、ここで前のアニメーションから何秒遅らせて実行するかを設定できます。SPAは基本的に遷移後のページのロードはなく遷移する動作自体は一瞬で終わってしまうので、1秒遅らせることで視覚的にアニメーションが行われていることが分かりやすくなります。