Skip to content
sumnail

Vue3のTransitionコンポーネントでアニメーションを実装

created at : 2024/08/03

Vue3
CSS
アニメーション
Transition

実装方法

Transition コンポーネントを使用してアニメーションを実装してみます。

サンプル

ボタンをクリックすると、テキストがアニメーションと共に表示されます。

Transition のサンプル

使用方法

Transition コンポーネントを使用するには、以下のように記述します。

  • template:
    Transition コンポーネント内に、アニメーションを実装したい部分を記述します。
  • style:
    アニメーションのスタイルを記述します。v-enter-from、v-enter-active、v-leave-to、v-leave-active などのクラスを指定します。
vue
<template>
  <button @click="show = !show">{{show ? "Fade Out Text" : "Fade In Text"}}</button>
  <Transition>
    <p v-if="show">Hello, World.</p>
  </Transition>
</template>
vue
<script setup lang="ts">
import { ref } from 'vue';

const show = ref(false);
</script>
vue
<style scoped>
/* 以下がTransitionの記述 */
.v-enter-active,
.v-leave-active {
  transition: opacity 0.5s ease;
}

.v-enter-from,
.v-leave-to {
  opacity: 0;
}
/* ここまでがTransitionの記述 */

button {
  margin: 8px;
  padding: 8px 16px;
  border-radius: 4px;
  background-color: var(--main-color);
}

button:hover {
  background-color: var(--main-hover-color);
}
</style>

Props

Transition コンポーネントには、以下のプロパティが設定出来ます。

props:

  • name: アニメーション名を指定します。
  • appear: 初回表示時にアニメーションを適用します。
  • mode: アニメーションのモードを指定します。
  • duration: アニメーションの時間を指定します。
  • enter-from-class: 入場時のクラスを指定します。
  • enter-active-lass: 入場時のアクティブクラスを指定します。
  • enter-to-class: 入場時の終了クラスを指定します。
  • leave-from-class: 退場時のクラスを指定します。
  • leave-active-class: 退場時のアクティブクラスを指定します。
  • leave-to-class: 退場時の終了クラスを指定します。

実装例

Transition コンポーネントを使用して、様々なアニメーションを実装してみます。

Fade up

sample

コード
vue
<template>
  <button @click="show = !show">{{show ? "Fade Text" : "Fade Text"}}</button>
  <Transition name="fade-up">
    <p v-if="show">Hello, World.</p>
  </Transition>
</template>
vue
<script setup lang="ts">
import { ref } from 'vue';

const show = ref(false);
</script>
vue
<style scoped>
.fade-up-enter-active,
.fade-up-leave-active {
  transition: opacity 0.5s ease, transform 0.5s ease;
}

.fade-up-enter-from,
.fade-up-leave-to {
  opacity: 0;
  transform: translateY(20px);
}

button {
  margin: 8px;
  padding: 8px 16px;
  border-radius: 4px;
  background-color: var(--main-color);
}

button:hover {
  background-color: var(--main-hover-color);
}
</style>

Fade down

sample

コード
vue
<template>
  <button @click="show = !show">{{show ? "Fade Text" : "Fade Text"}}</button>
  <Transition name="fade-down">
    <p v-if="show">Hello, World.</p>
  </Transition>
</template>
vue
<script setup lang="ts">
import { ref } from 'vue';

const show = ref(false);
</script>
vue
<style scoped>
.fade-down-enter-active,
.fade-down-leave-active {
  transition: opacity 0.5s ease, transform 0.5s ease;
}

.fade-down-enter-from,
.fade-down-leave-to {
  opacity: 0;
  transform: translateY(-20px);
}

button {
  margin: 8px;
  padding: 8px 16px;
  border-radius: 4px;
  background-color: var(--main-color);
}

button:hover {
  background-color: var(--main-hover-color);
}
</style>

Rotate

sample

Hover over the box

コード
vue
<template>
  <div class="parent-box" @mouseover="() => show = true" @mouseleave="() => show = false">
    <p v-if="!show">Hover over the box</p>
    <Transition name="rotate">
      <div v-if="show" class="box" >
        <p>Hello, World.</p>
      </div>
    </Transition>
  </div>
</template>
vue
<script setup lang="ts">
import { ref } from 'vue';

const show = ref(false);
</script>
vue
<style scoped>
.rotate-enter-active,
.rotate-leave-active {
  transition: transform 0.5s ease;
}

.rotate-enter-from,
.rotate-leave-to {
  transform: rotate(0deg);
}

.rotate-enter-to,
.rotate-leave-from {
  transform: rotate(360deg);
}

.parent-box {
  width: 100px;
  height: 100px;
  position: relative;
  border: 1px solid var(--main-color);
  padding: 8px;
}

.box {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  padding: 8px;
  background-color: var(--main-color);
}

.slide {
  background-color: var(--secondary-color);
}
</style>

Flip

sample

Hover over the box

コード
vue
<template>
  <div class="parent-box" @mouseover="() => show = true" @mouseleave="() => show = false">
    <p v-if="!show">Hover over the box</p>
    <Transition name="flip">
      <div v-if="show" class="box" >
        <p>Hello, World.</p>
      </div>
    </Transition>
  </div>
</template>
vue
<script setup lang="ts">
import { ref } from 'vue';

const show = ref(false);
</script>
vue
<style scoped>
.flip-enter-active,
.flip-leave-active {
  transition: transform 0.5s ease;
}

.flip-enter-from,
.flip-leave-to {
  transform: rotateY(180deg);
}

.flip-enter-to,
.flip-leave-from {
  transform: rotateY(0deg);
}

.parent-box {
  width: 100px;
  height: 100px;
  position: relative;
  border: 1px solid var(--main-color);
  padding: 8px;
}

.box {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  padding: 8px;
  background-color: var(--main-color);
}

.slide {
  background-color: var(--secondary-color);
}
</style>

Bounce

sample

Hover over the box

コード
vue
<template>
  <div class="parent-box" @mouseover="() => show = true" @mouseleave="() => show = false">
    <p v-if="!show">Hover over the box</p>
    <Transition name="bounce">
      <div v-if="show" class="box" >
        <p>Hello, World.</p>
      </div>
    </Transition>
  </div>
</template>
vue
<script setup lang="ts">
import { ref } from 'vue';

const show = ref(false);
</script>
vue
<style scoped>
.bounce-enter-active,
.bounce-leave-active {
  animation: bounce 0.5s ease;
}

@keyframes bounce {
  from, to { transform: scale(1, 1); }
  25% { transform: scale(0.9, 1.1); }
  50% { transform: scale(1.1, 0.9); }
  75% { transform: scale(0.95, 1.05); }
}

.parent-box {
  width: 100px;
  height: 100px;
  position: relative;
  border: 1px solid var(--main-color);
  padding: 8px;
}

.box {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  padding: 8px;
  background-color: var(--main-color);
}
</style>

Flash

sample

Hover over the box

コード
vue
<template>
  <div class="parent-box" @mouseover="() => show = true" @mouseleave="() => show = false">
    <p v-if="!show">Hover over the box</p>
    <Transition name="flash">
      <div v-if="show" class="box" >
        <p>Hello, World.</p>
      </div>
    </Transition>
  </div>
</template>
vue
<script setup lang="ts">
import { ref } from 'vue';

const show = ref(false);
</script>
vue
<style scoped>
.flash-enter-active {
  animation: flash 0.5s ease;
}

@keyframes flash {
  from, to { opacity: 1; }
  25% { opacity: 0; }
  50% { opacity: 1; }
  75% { opacity: 0; }
}

.parent-box {
  width: 100px;
  height: 100px;
  position: relative;
  border: 1px solid var(--main-color);
  padding: 8px;
}

.box {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  padding: 8px;
  background-color: var(--main-color);
}

.slide {
  background-color: var(--secondary-color);
}
</style>

Shake

sample

Hover over the box

コード
vue
<template>
  <div class="parent-box" @mouseover="() => show = true" @mouseleave="() => show = false">
    <p v-if="!show">Hover over the box</p>
    <Transition name="shake">
      <div v-if="show" class="box" >
        <p>Hello, World.</p>
      </div>
    </Transition>
  </div>
</template>
vue
<script setup lang="ts">
import { ref } from 'vue';

const show = ref(false);
</script>
vue
<style scoped>
.shake-enter-active {
  animation: shake 0.5s ease;
}

@keyframes shake {
  10%,
  90% {
    transform: translate3d(-1px, 0, 0) rotate(0deg);
  }

  20%,
  80% {
    transform: translate3d(2px, 0, 0) rotate(-1deg);
  }

  30%,
  50%,
  70% {
    transform: translate3d(-4px, 0, 0) rotate(1deg);
  }

  40%,
  60% {
    transform: translate3d(4px, 0, 0) rotate(0deg);
  }
}

.parent-box {
  width: 100px;
  height: 100px;
  position: relative;
  border: 1px solid var(--main-color);
  padding: 8px;
}

.box {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  padding: 8px;
  background-color: var(--main-color);
}

.slide {
  background-color: var(--secondary-color);
}
</style>

Pulse

sample

Hover over the box

コード
vue
<template>
  <div class="parent-box" @mouseover="() => show = true" @mouseleave="() => show = false">
    <p v-if="!show">Hover over the box</p>
    <Transition name="pulse">
      <div v-if="show" class="box" >
        <p>Hello, World.</p>
      </div>
    </Transition>
  </div>
</template>
vue
<script setup lang="ts">
import { ref } from 'vue';

const show = ref(false);
</script>
vue
<style scoped>
.pulse-enter-active {
  animation: pulse 0.5s ease;
}

@keyframes pulse {
  0%,40%,80% {
    transform: scale(1);
  }
  10%,50%,90% {
    transform: scale(1.1);
  }
  20%,60%,100% {
    transform: scale(1);
  }
  30%,70% {
    transform: scale(0.9);
  }
}

.parent-box {
  width: 100px;
  height: 100px;
  position: relative;
  border: 1px solid var(--main-color);
  padding: 8px;
}

.box {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  padding: 8px;
  background-color: var(--main-color);
}

.slide {
  background-color: var(--secondary-color);
}
</style>

参考