404 Not Found

404 Not Found


nginx

Vue 3 のトランジションとアニメーション:Transition、TransitionGroup、6つのCSSクラス、およびJSフック

トランジションやアニメーションは、Vue アプリをよりダイナミックなものにします。要素がビューポートに出入りする際の滑らかなトランジションや、リストが変更された際の洗練された再描画などが挙げられます。Vue には <Transition> および <TransitionGroup> コンポーネントが含まれており、これらは CSS クラス名や JavaScript フックと連携して、さまざまなアニメーション効果を実現します。

遷移アニメーションをマスターすることは、ユーザー体験の向上の鍵となります。優れたアニメーションは、アプリに「スムーズで、反応が良く、プロフェッショナルな」印象を与えます。

1. 学習内容


2. 「タブ切り替え」ハードスイッチの扱いにくさ

(1) 課題:コンポーネントが突然消えたり現れたりすること、UIがちらつくこと

アリスの管理画面にはタブ切り替え機能がありました:

VUE
<!-- ❌ The "Flip" Version:v-if Sudden Switch -->
<template>
  <button @click="currentTab = 'home'">Home</button>
  <button @click="currentTab = 'profile'">Profile</button>
  
  <div v-if="currentTab === 'home'">Home Content</div>
  <div v-else-if="currentTab === 'profile'">Profile Content</div>
</template>

ユーザー体験:

(2) Vueのトランジション実装:タグ1つ、クラス6つ

VUE
<!-- ✅ Correct Version:Smooth Transition -->
<template>
  <button @click="currentTab = 'home'">Home</button>
  <button @click="currentTab = 'profile'">Profile</button>
  
  <Transition name="fade" mode="out-in">
    <div v-if="currentTab === 'home'" key="home">Home Content</div>
    <div v-else-if="currentTab === 'profile'" key="profile">Profile Content</div>
  </Transition>
</template>

<style>
.fade-enter-active, .fade-leave-active {
  transition: opacity 0.3s;
}
.fade-enter-from, .fade-leave-to {
  opacity: 0;
}
</style>

ユーザー体験:

(3) 収益

トランジションを追加した後:


3. 遷移:単一要素

(1) 基本的な使い方

VUE
<template>
  <button @click="show = !show">Toggle</button>
  
  <Transition name="fade">
    <p v-if="show">Hello Vue</p>
  </Transition>
</template>

<style>
/* 6 CSS classes, Vue Auto-add/Remove */
.fade-enter-active, .fade-leave-active {
  transition: opacity 0.5s ease;
}
.fade-enter-from, .fade-leave-to {
  opacity: 0;
}
</style>

(2) 6つのCSSクラスの詳細な解説

クラス トリガー条件 目的
v-enter-from 要素挿入前 初期状態
v-enter-active 要素挿入の全プロセス 遷移プロセス
v-enter-to 要素を挿入した後 最終状態
v-leave-from 要素が離れる前に 初期状態
v-leave-active 要素がプロセス全体から離れる 遷移プロセス
v-leave-to 要素が離れた後 終了状態

(3) 命名規則

VUE
<!-- v-bind:name="fade" → 6 classes are .fade-xxx -->
<Transition name="fade">...</Transition>

<!-- Don't write name → Default v-xxx (6 classes are .v-xxx) -->
<Transition>...</Transition>

<!-- News name -->
<Transition :name="transitionName">...</Transition>

(4) 3つのモード

VUE
<!-- 1. Default Mode:Entry and exit occur simultaneously(Overlap) -->
<Transition name="fade">
  <div v-if="show">Content</div>
</Transition>

<!-- 2. out-in:Leave first, then enter(Recommendations,Avoid Overlapping) -->
<Transition name="fade" mode="out-in">
  <div v-if="show">Content</div>
</Transition>

<!-- 3. in-out:Enter first, then leave(Rare) -->
<Transition name="fade" mode="in-out">
  <div v-if="show">Content</div>
</Transition>

4. CSSアニメーションの5つの種類

(1) フェードインとフェードアウト(最も一般的)

CSS
.fade-enter-active, .fade-leave-active {
  transition: opacity 0.3s;
}
.fade-enter-from, .fade-leave-to {
  opacity: 0;
}

(2) スライド

CSS
.slide-enter-active, .slide-leave-active {
  transition: transform 0.3s;
}
.slide-enter-from {
  transform: translateX(-100%);
}
.slide-leave-to {
  transform: translateX(100%);
}

(3) ズーム

CSS
.scale-enter-active, .scale-leave-active {
  transition: transform 0.3s;
}
.scale-enter-from, .scale-leave-to {
  transform: scale(0);
}

(4) 回転

CSS
.rotate-enter-active {
  transition: transform 1s;
}
.rotate-enter-from {
  transform: rotate(0deg);
}
.rotate-leave-active {
  animation: bounce 0.5s;
}
@keyframes bounce {
  0% { transform: scale(0); }
  50% { transform: scale(1.2); }
  100% { transform: scale(1); }
}

(5) 複合アニメーション

CSS
.combo-enter-active, .combo-leave-active {
  transition: all 0.3s;
}
.combo-enter-from {
  opacity: 0;
  transform: translateX(-50px) scale(0.8);
}
.combo-leave-to {
  opacity: 0;
  transform: translateX(50px) scale(0.8);
}

5. TransitionGroupのリストアニメーション

(1) 基本的な使い方

VUE
<template>
  <button @click="add">Add</button>
  
  <TransitionGroup name="list" tag="ul">
    <li v-for="item in items" :key="item.id">
      {{ item.name }}
      <button @click="remove(item.id)">×</button>
    </li>
  </TransitionGroup>
</template>

<script setup>
import { ref } from 'vue'
const items = ref([
  { id: 1, name: 'Apple' },
  { id: 2, name: 'Banana' }
])

function add() {
  const id = Date.now()
  items.value.push({ id, name: `Item ${id}` })
}

function remove(id) {
  items.value = items.value.filter(i => i.id !== id)
}
</script>

<style>
/* 6 classes, However, for list items, enter/leave/move */
.list-enter-active, .list-leave-active {
  transition: all 0.5s;
}
.list-enter-from, .list-leave-to {
  opacity: 0;
  transform: translateX(30px);
}
.list-leave-active {
  position: absolute;  /* Remove from the document flow when leaving */
}
/* Animation when list items move */
.list-move {
  transition: transform 0.5s;
}
</style>

(2) 要点:.list-move

CSS
/* When the position of a list item changes(As sorted),Apply Automatically .list-move */
.list-move {
  transition: transform 0.5s;
}

(3) リストアニメーションの5つの主なシナリオ

シーン アニメーション
アイテムを追加 フェードイン+スライドダウン
項目を削除 フェードアウト+左スワイプ
並べ替え 新しい位置へスムーズに移動
フィルター 削除されるアイテムはフェードアウト、残すアイテムはスムーズな遷移
ドラッグ マウスの動きをリアルタイムで追従

6. JavaScriptのフック

(1) 8つのJavaScriptフック

VUE
<template>
  <Transition
    @before-enter="beforeEnter"
    @enter="enter"
    @after-enter="afterEnter"
    @before-leave="beforeLeave"
    @leave="leave"
    @after-leave="afterLeave"
    :css="false"  <!-- Disable CSS class -->
  >
    <p v-if="show">Hello</p>
  </Transition>
</template>

<script setup>
import gsap from 'gsap'

function beforeEnter(el) {
  console.log('Before enter:', el)
}

function enter(el, done) {
  gsap.to(el, {
    opacity: 1,
    y: 0,
    duration: 0.5,
    onComplete: done  // Notification Complete
  })
}

function afterEnter(el) {
  console.log('After enter:', el)
}

// leave / beforeLeave / afterLeave Similar
</script>

(2) GSAPとの連携(推奨)

BASH
npm install gsap
VUE
<template>
  <Transition :css="false" @enter="onEnter" @leave="onLeave">
    <p v-if="show">Hello GSAP</p>
  </Transition>
</template>

<script setup>
import gsap from 'gsap'

function onEnter(el, done) {
  gsap.fromTo(el, 
    { opacity: 0, y: 50 },
    { opacity: 1, y: 0, duration: 0.5, onComplete: done }
  )
}

function onLeave(el, done) {
  gsap.to(el, { opacity: 0, y: -50, duration: 0.3, onComplete: done })
}
</script>

7. サードパーティ製のアニメーションライブラリ

(1) Animate.css の統合

BASH
npm install animate.css
JS
// main.js
import 'animate.css'
VUE
<template>
  <Transition
    enter-active-class="animate__animated animate__fadeIn"
    leave-active-class="animate__animated animate__fadeOut"
  >
    <p v-if="show">Hello</p>
  </Transition>
</template>

(2) @vueuse/motion

BASH
npm install @vueuse/motion
JS
// main.js
import { MotionPlugin } from '@vueuse/motion'
app.use(MotionPlugin)
VUE
<template>
  <div v-motion :initial="{ opacity: 0, y: 50 }" :enter="{ opacity: 1, y: 0 }">
    Fade in from below
  </div>
</template>

(3) GSAPの推奨ユースケース

ライブラリ 評価 対象
CSS アニメーション ⭐⭐⭐⭐⭐ シンプルなトランジション、フェード
Animate.css ⭐⭐⭐⭐ 多種多様なプリセットアニメーション
@vueuse/motion ⭐⭐⭐⭐ 宣言型で、Vueとの統合性に優れている
GSAP ⭐⭐⭐⭐⭐ 複雑なタイムライン、物理演算に基づくアニメーション

8. 完全な事例:5つの主要な移行シナリオ

(1) ▶ サンプル:. CSSアニメーションの5つの種類

CSS
/* 1. Fade In, Fade Out */
.fade-enter-active, .fade-leave-active { transition: opacity 0.3s; }
.fade-enter-from, .fade-leave-to { opacity: 0; }

/* 2. Slide */
.slide-enter-active, .slide-leave-active { transition: transform 0.3s; }
.slide-enter-from { transform: translateX(-100%); }
.slide-leave-to { transform: translateX(100%); }

/* 3. Zoom */
.scale-enter-active, .scale-leave-active { transition: transform 0.3s; }
.scale-enter-from, .scale-leave-to { transform: scale(0); }

/* 4. Rotation */
.rotate-enter-active { transition: transform 1s; }
.rotate-enter-from { transform: rotate(0deg); }
.rotate-leave-active { animation: spin 0.5s; }

/* 5. Combination */
.combo-enter-active, .combo-leave-active { transition: all 0.3s; }
.combo-enter-from { opacity: 0; transform: translateX(-50px) scale(0.8); }
▶ 試してみよう

(2) ▶ サンプル:. 6つのCSSクラスの詳細な説明

クラス トリガー
.fade-enter-from 要素を挿入する前に
.fade-enter-active 要素挿入プロセス
.fade-enter-to 要素を挿入した後
.fade-leave-from エレメントが去る前に
.fade-leave-active 要素の離脱プロセス
.fade-leave-to 『エレメントが去った後』

(3) ▶ サンプル:. TransitionGroup リストアニメーション

VUE
<TransitionGroup name="list" tag="ul">
  <li v-for="item in items" :key="item.id">
    {{ item.name }}
  </li>
</TransitionGroup>

<style>
.list-enter-active, .list-leave-active {
  transition: all 0.5s;
}
.list-move { transition: transform 0.5s; }
</style>
▶ 試してみよう

(4) ▶ サンプル:. 主要なサードパーティ製アニメーションライブラリ5選

ライブラリ コマンド 適用対象
CSS なし(組み込み) シンプル
Animate.css npm i animate.css プリセットアニメーション
@vueuse/motion npm i @vueuse/motion 宣言型
GSAP npm i gsap 複雑なタイムライン
Motion One npm i motion 軽量なWebアニメーション

(5) ▶ サンプル:. よくある5つの間違いに関するクイックリファレンス

エラー 症状 解決策
遷移が反映されない 要素が即座に消える <Transition> ラッパー + v-if を追加
v-for にアニメーションなし リスト項目間のトランジションなし <TransitionGroup> を使用
並べ替え時にアニメーションが表示されない 移動時にカクつきがある .list-move クラスを追加
複数のコンポーネント間の同時切り替え 重複 区別するために key を追加 + mode="out-in"
CSSアニメーションの速度が速すぎる/遅すぎる ユーザー体験の低下 トランジションの持続時間を0.2~0.5秒に調整する

(6) ▶ サンプル:. 5つの実践的なシナリオ

シーン アニメーション
タブの切り替え フェード(アウト→イン)
モーダルダイアログ 拡大・縮小 + フェード
リストへの追加・削除 リストのアニメーション
ルート切り替え フェード+スライド
トースト通知 上からスライド表示 + 自動消去

❓ よくある質問

Q CSSトランジションとCSS @keyframesのどちらを選べばいいですか?
A 単純なトランジション(不透明度やトランスフォームなど)にはCSSトランジションを使用してください。複雑なアニメーション(多段階、物理演算ベースなど)には@keyframesまたはGSAPを使用してください。Vue Transitionsは両方をサポートしています。
Q TransitionGroup では :key セレクタが必要ですか?
A はい。<TransitionGroup> 子要素は :key を使用して一意に識別する必要があります。そうしないと、アニメーションがトリガーされません。
Q 「ページ遷移」アニメーションを実装するにはどうすればよいですか?
A <router-view v-slot="{ Component }"> + <Transition> で囲んでください。ルートが変わるたびにコンポーネントが切り替わり、遷移がトリガーされます。
Q mode="out-in"?の目的は何ですか?
A これは、表示を終了するコンポーネントのアニメーションが終了してから、表示を開始するコンポーネントのアニメーションが始まるようにするためのものです。これにより、両方のコンポーネントが同時に表示される(重なる)ことを防ぎます。
Q JavaScriptフックとCSSクラスは併用できますか?
A はい。<Transition :css="false" @enter="onEnter"> CSSクラスを無効にして、JavaScriptフックのみを使用することもできます。あるいは、両方を有効にすることも可能です(スタイリングにはCSSクラスを、コールバックにはJavaScriptフックを使用します)。
Q アニメーションの動作が遅い場合はどうすればよいですか?
A (1) transform および opacity(GPU アクセラレーション対応)を使用する;(2) レイアウトをトリガーするプロパティ(width、height、top)の使用を避ける;(3) 同時にアニメーション処理される要素の数を減らす。
Q VueでAnimate.cssを使うにはどうすればよいですか?
A enter-active-class="animate__animated animate__fadeIn" を使用して、Animate.cssのクラス名をVueのフックにマッピングしてください。

📖 まとめ


📝 練習問題

(1) 基礎問題(難易度:⭐)

シンプルなフェードイン/フェードアウト機能を持つモーダルを実装する:

(2) 上級問題(難易度:⭐⭐)

TransitionGroup によるリストアニメーションを実装する:

(3) チャレンジ問題(難易度:⭐⭐⭐)

完全な「ページ遷移アニメーション」システムを実装する:

  1. ルート切り替え時のフェード+スライドアニメーション
  2. リスト内の項目の追加、削除、並べ替えを行うための3種類のアニメーション
  3. モーダルポップアップにおける「拡大+フェード」の組み合わせ
  4. GSAPとの連携による複雑なタイムラインアニメーション
  5. 5つのサードパーティ製アニメーションライブラリの比較テスト
  6. パフォーマンスの最適化(GPU アクセラレーション + 変更予定)
Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%