🗂

[和訳] Nuxt3 公式サイト~Transitions

2023/01/25に公開

この記事について

この記事はNuxt3 公式サイト Transitions を和訳したものになります(日本語が不自然になってしまっている箇所があるのはごめんなさい)。
https://nuxt.com/docs/getting-started/transitions
所々自分の理解のために参考になりそうな別サイトのリンクを貼ってあります。

Transitions

Nuxt は Vue の <Transition> コンポーネントを利用してページとレイアウト間の遷移を適用します。

Page transitions

ページの遷移を有効にすると、全てのページで自動遷移を適用できます。

nuxt.config.ts
export default defineNuxtConfig({
  app: {
    pageTransition: { name: 'page', mode: 'out-in' }
  },
})

ページ間の遷移を追加するには、app.vue に次の CSS を追加します。

app.vue
<template>
  <NuxtPage />
</template>
<style>
.page-enter-active,
.page-leave-active {
  transition: all 0.4s;
}
.page-enter-from,
.page-leave-to {
  opacity: 0;
  filter: blur(1rem);
}
</style>
pages/index.vue
<template>
  <div>
    <h1>Home page</h1>
    <NuxtLink to="/about">About page</NuxtLink>
  </div>
</template>
pages/about.vue
<template>
  <div>
    <h1>About page</h1>
    <NuxtLink to="/">Home page</NuxtLink>
  </div>
</template>

※公式サイトでは、上記設定を適用させた際の遷移の様子が動画で見られます。


ページごとに異なる遷移を設定するには、ページの definePageMetapageTransition キーを設定します。

pages/about.vue
<script setup lang="ts">
definePageMeta({
  pageTransition: {
    name: 'rotate'
  }
})
</script>
app.vue
<template>
  <NuxtPage />
</template>

<style>
/* ... */
.rotate-enter-active,
.rotate-leave-active {
  transition: all 0.4s;
}
.rotate-enter-from,
.rotate-leave-to {
  opacity: 0;
  transform: rotate3d(1, 1, 1, 15deg);
}
</style>

※公式サイトでは、上記設定を適用させた際の遷移の様子が動画で見られます。

Layout transitions

レイアウトトランジションを有効にすると、全てのレイアウトに自動トランジションが適用されます。

nuxt.config.ts
export default defineNuxtConfig({
  app: {
    layoutTransition: { name: 'layout', mode: 'out-in' }
  },
})

ページとレイアウト間の遷移を追加するには、以下の CSS を app.vue に追加してください。

app.vue
<template>
  <NuxtLayout>
    <NuxtPage />
  </NuxtLayout>
</template>

<style>
.layout-enter-active,
.layout-leave-active {
  transition: all 0.4s;
}
.layout-enter-from,
.layout-leave-to {
  filter: grayscale(1);
}
</style>
layouts/default.vue
<template>
  <div>
    <pre>default layout</pre>
    <slot />
  </div>
</template>

<style scoped>
div {
  background-color: lightgreen;
}
</style>
layouts/orange.vue
<template>
  <div>
    <pre>orange layout</pre>
    <slot />
  </div>
</template>

<style scoped>
div {
  background-color: #eebb90;
  padding: 20px;
  height: 100vh;
}
</style>
pages/index.vue
<template>
  <div>
    <h1>Home page</h1>
    <NuxtLink to="/about">About page</NuxtLink>
  </div>
</template>
pages/about.vue
<script setup lang="ts">
definePageMeta({
  layout: 'orange'
})
</script>

<template>
  <div>
    <h1>About page</h1>
    <NuxtLink to="/">Home page</NuxtLink>
  </div>
</template>

※公式サイトでは、上記設定を適用させた際の遷移の様子が動画で見られます。


pageTransition と同様に、definePageMeta を使用して、カスタムした layoutTransition をページコンポーネントに適用することができます。

pages/about.vue
<script setup lang="ts">
definePageMeta({
  layout: 'orange',
  layoutTransition: {
    name: 'slide-in'
  }
})
</script>

Global settings

これらのデフォルトのトランジション名は、nuxt.config を使用してグローバルにカスタマイズすることができます。

pageTransitionlayoutTransition の両キーは、カスタム CSS トランジションの名前、モード、その他の有効なトランジションプロパティを渡す TransitionProps をシリアライズ可能な JSON の値として受け取ります。

nuxt.config.ts
export default defineNuxtConfig({
  app: {
    pageTransition: {
      name: 'fade',
      mode: 'out-in' // default
    },
    layoutTransition: {
      name: 'slide',
      mode: 'out-in' // default
    }
  }
})

name プロパティを変更した場合、それに応じて CSS のクラス名も変更する必要があります。

グローバルに設定した遷移プロパティを上書きするには、defineMetaPage を使用して単一の Nuxt のページまたはレイアウトを定義し、nuxt.config ファイルでグローバルに定義されているページまたはレイアウト遷移を全て上書きしてください。

pages/some-page.vue
<script setup lang="ts">
definePageMeta({
  pageTransition: {
    name: 'bounce',
    mode: 'out-in' // default
  }
})
</script>

Disable transitions

pageTransitionlayoutTransition は特定のルートに対して無効にすることができます。

pages/some-page.vue
<script setup lang="ts">
definePageMeta({
  pageTransition: false
  layoutTransition: false
})
</script>

グローバルに無効にしたいときは下のようにします。

nuxt.config.ts
defineNuxtConfig({
  app: {
    pageTransition: false,
    layoutTransition: false
  }
})

JavaScript Hooks

発展的な使用例として、JavaScript hook を使用して高度に動的なカスタムトランジションを Nuxt ページに作成することができます。

この方法は GSAP や Tween.js のようなJavaScript アニメーションライブラリの完璧な使用方法を提供します。
https://greensock.com/gsap/
https://github.com/tweenjs/tween.js/

pages/some-page.vue
<script setup lang="ts">
definePageMeta({
  pageTransition: {
    name: 'custom-flip',
    mode: 'out-in',
    onBeforeEnter: (el) => {
      console.log('Before enter...')
    },
    onEnter: (el, done) => {},
    onAfterEnter: (el) => {}
  }
})
</script>

詳細は下記ページを参照してください。
https://vuejs.org/guide/built-ins/transition.html#javascript-hooks

Dynamic transitions

条件付きのロジックで動的な遷移を適用するために、インラインミドルウェアを活用して、to.meta.pageTransition に異なる遷移名を割り当てることができます。

pages/[id].vue
<script setup lang="ts">
definePageMeta({
  pageTransition: {
    name: 'slide-right',
    mode: 'out-in'
  },
  middleware (to, from) {
    to.meta.pageTransition.name = +to.params.id > +from.params.id ? 'slide-left' : 'slide-right'
  }
})
</script>

<template>
  <h1>#{{ $route.params.id }}</h1>
</template>

<style>
.slide-left-enter-active,
.slide-left-leave-active,
.slide-right-enter-active,
.slide-right-leave-active {
  transition: all 0.2s;
}
.slide-left-enter-from {
  opacity: 0;
  transform: translate(50px, 0);
}
.slide-left-leave-to {
  opacity: 0;
  transform: translate(-50px, 0);
}
.slide-right-enter-from {
  opacity: 0;
  transform: translate(-50px, 0);
}
.slide-right-leave-to {
  opacity: 0;
  transform: translate(50px, 0);
}
</style>
layouts/default.vue
<script setup lang="ts">
const route = useRoute()
const id = computed(() => Number(route.params.id || 1))
const prev = computed(() => '/' + (id.value - 1))
const next = computed(() => '/' + (id.value + 1))
</script>

<template>
  <div>
    <slot />
    <div v-if="$route.params.id">
      <NuxtLink :to="prev">⬅️</NuxtLink> |
      <NuxtLink :to="next">➡️</NuxtLink>
    </div>
  </div>
</template>

前の id に移動するときには slide-left、次の id に遷移するときには slide-right という遷移が適用されるようになります。
※公式サイトでは、上記設定を適用させた際の遷移の様子が動画で見られます。

Transition with NuxtPage

app.vue<NuxtPage /> を使用する場合、遷移に関するプロパティをとしてコンポーネントのプロパティとして直接渡すことで、グローバルな遷移を有効にできます。

app.vue
<template>
  <div>
    <NuxtLayout>
      <NuxtPage :transition="{
        name: 'bounce',
        mode: 'out-in'
      }" />
    </NuxtLayout>
  </div>
</template>
GitHubで編集を提案

Discussion