Nuxt Nation カンファレンス開催!11月12日~13日参加しましょう。

vue-transitions
@morev/vue-transitions

CSS不要のリユース可能なインターフェーストランジション ❤️

Promo image of @morev/vue-transitions package

Stability of "master" branchLicense: MITLast commitRelease versionGitHub Release DateKeywords

@morev/vue-transitions

CSS不要のVue 2Vue 3対応、リユース可能なインターフェーストランジション ❤️

✔️ プロップスによる高度なカスタマイズが可能;
✔️ groupモードでグリッド/フレックスレイアウトと正しく動作;
✔️ transformopacityなどのアニメーション要素の初期スタイルを考慮;
✔️ ユニバーサルなNuxt 2およびNuxt 3モジュールでさらに使いやすくなりました。

デモ/プレイグラウンド

目次

インストール

❗ 要件

  • Nodeバージョン: >= 18.0.0
  • Nuxtバージョン(使用する場合):>= 2.17.0 || >= 3.5.0

指定されたバージョンよりも古いNodeまたはNuxtバージョンを使用している場合、プラグインは動作しません。


yarnの使用

yarn add @morev/vue-transitions

npmの使用

npm install @morev/vue-transitions

pnpmの使用

pnpm add @morev/vue-transitions

bunの使用

bun add @morev/vue-transitions

Bunユーザーへの**重要な注意**

このパッケージは、Vueのバージョンを特定し、適切なコンポーネントを提供するためにpostinstallフックに依存しています。
デフォルトでは、Bunはライフサイクルフックを実行しません。そのため、動作させるには、インストール後にtrustedDependenciesにパッケージを手動で追加し、bun installを再度実行する必要があります。

{
  "trustedDependencies": ["@morev/vue-transitions"]
}

使用方法

Nuxtでライブラリを使用する場合は、次の段落はスキップできます。
「Nuxtでの使用」セクションに移動.

パッケージは2つのバージョンのコンポーネントをエクスポートします

  • Vue2用バージョンは、名前付きエクスポート/vue2で利用できます
  • Vue3用バージョンは、名前付きエクスポート/vue3で利用できます

ただし、使用されているVueのローカルバージョンにマップされたデフォルトエクスポートもあります。
内部的には、postinstall npmフックを利用しています。
パッケージをインストールすると、スクリプトがインストールされているVueのバージョンをチェックし、ローカルのVueバージョンに基づいてエクスポートをリダイレクトします。

かなり堅牢に感じますが、心配な場合は、使用しているバージョンに応じた明示的な名前付きインポートを使用することをお勧めします。

ちなみに、インストール後にデフォルトのエクスポートを変更できます。vue-transitions-version-switch <version>コマンドを実行するだけです。

  • yarnを使用した例:yarn vue-transitions-version-switch 2
  • npxを使用した例:npx vue-transitions-version-switch 3

グローバル登録

Vue3の使用

import { createApp } from 'vue';
import { plugin as vueTransitionsPlugin } from '@morev/vue-transitions';
import '@morev/vue-transitions/styles';

const app = createApp(App);

app.use(vueTransitionsPlugin({
  // Plugin options (optional, described below)
}));

Vue2の使用

import Vue from 'vue';
import { plugin as vueTransitionsPlugin } from '@morev/vue-transitions';
import '@morev/vue-transitions/styles';

Vue.use(vueTransitionsPlugin, {
  // Plugin options (optional, described below)
});
😥 「この依存関係が見つかりませんでした」というエラーが発生しました

exportsフィールドを解決できない環境(Nuxt 2など)では、スタイルのインポートをファイルへの直接パスに置き換えてください。

- import '@morev/vue-transitions/styles';
+ import '@morev/vue-transitions/dist/index.css';

カスタムオプション

カスタムオプションを設定する場合は、デフォルトエクスポートではなく名前付きエクスポートpluginを使用することをお勧めします。これにより、適切な型情報が得られます。

カスタムオプションを使用すると、デフォルトのプロパティ値を変更できます。
デフォルト値を変更するには、目的のプロップスのキーと値のペアをリストしたdefaultPropsキーをプラグイン設定に渡します。
コンポーネントごとにデフォルトのプロップスを変更することもできます。そのためには、componentDefaultPropsキーをプラグイン設定に渡します。

**重要**:これらのプロップスは検証されないため、正しい値で定義してください。

import { createApp } from 'vue';
import { plugin as vueTransitionsPlugin } from '@morev/vue-transitions';
import '@morev/vue-transitions/styles';

const app = createApp(App);

app.use(vueTransitionsPlugin({
  // Default duration for all transitions now is `200`
  defaultProps: {
    duration: 200,
  },
  // But for `<transition-expand>` default duration is `500`
  componentDefaultProps: {
    TransitionExpand: {
      duration: 500,
    }
  }
}));

コンポーネントの直接インポート

<template>
  <transition-fade>
    <div v-if="isVisible" class="box">
      Fade transition
    </div>
  </transition-fade>
</template>

<script>
  import { TransitionFade } from '@morev/vue-transitions';

  export default {
    components: { TransitionFade },
  };
</script>

Nuxtでの使用

このライブラリは、名前付きエクスポート/nuxtを介して、Nuxt 2および3用のすぐに使用できるユニバーサルモジュールをエクスポートします。
Nuxtを使用する場合、手動インストールではなくモジュールを使用することをお勧めします。

  1. Nuxtを使用すると、グローバル登録ではなく、オンデマンドでコンポーネントを自動インポートできるため、パフォーマンスが向上します。
  2. 単に高速です :)

@morev/vue-transitions/nuxtnuxt.config.tsまたはnuxt.config.jsmodulesセクションに追加します。

export default defineNuxtConfig({
  modules: [
    '@morev/vue-transitions/nuxt',
  ],
  vueTransitions: {
    // The same options as in the plugin itself.
    // You will get an autocomplete using Nuxt 3.
  }
});

トランジションコンポーネントをお楽しみください! 🎉

IntelliSense

Nuxtモジュールを使用する場合は、このセクションをスキップできます。Nuxtモジュールが自動的に処理します。

このセクションは、VSCodeの設定とコンポーネントのグローバル登録のみに適用されます。

Vue 2の場合

Vetur拡張機能をインストールしてVue 2を使用すると、すべてのコンポーネントがヒントを提供するため、操作は必要ありません。

Example of IntelliSense with VSCode and Vetur

Vue 3の場合

Volar拡張機能をインストールしてVue 3を使用すると、すべてのコンポーネントがヒントを提供するため、操作は必要ありません。

Example of IntelliSense with VSCode and Volar

トランジション一覧

TransitionFade

要素のopacityを変更する基本的なトランジション。非常にシンプルです。

コードを表示
<template>
  <transition-fade>
    <div v-if="isVisible">...</div>
  </transition-fade>
</template>

<script>
  import { TransitionFade } from '@morev/vue-transitions';

  export default {
    components: { TransitionFade },
  };
</script>

TransitionExpand

実際の要素サイズを操作するトランジション。
十分な年齢であれば、このトランジションをjQueryのslideUp/slideDownとして知っているかもしれません。
slideLeftslideRightのようにX軸でも動作します(ただし、実際に必要になるシナリオを考えるのは難しいです)。

個別プロップスaxis


TransitionSlide

transform: translate()を使用して要素の位置を操作するトランジション。
目的の要素の位置を計算するためにoffsetプロップスが必要であり、パーセンテージ値でも動作します。

offsetプロップスの使用方法の例
<template>
  <!--
    Element will fade in and fade out to top.
    Initial transform is `transform: translate(0, -16px)`
  -->
  <transition-slide :offset="[0, -16]"></transition-slide>

  <!--
    Element will fade in and fade out to bottom left side.
    Initial transform is `transform: translate(-16px, 16px)`
  -->
  <transition-slide :offset="[-16, 16]"></transition-slide>

  <!--
    Element will fade in and fade out to right,
    and the offset will be relative to the element width itself.
    Initial transform is `transform: translate(100%, 0)`
  -->
  <transition-slide :offset="['100%', 0]"></transition-slide>

  <!--
    Element will fade in from top and fade out to bottom,
    and the offset will be relative to the element height itself.

    Transform before element appears: `transform: translate(0, -100%)`
    Transform when element disappears: `transform: translate(0, 100%)`
  -->
  <transition-slide
    :offset="{
      enter: [0, '-100%'],
      leave: [0, '100%']
    }"
  ></transition-slide>
</template>

CSSを介して要素自体に適用されたtransformを尊重し、定義されたオフセットとマージします。
たとえば、中央揃えのドロップダウンを作成しようとする場合に非常に便利です。

👀 `transform`のマージの例を表示
<template>
  <div class="block">
    <!--
      In this case, given the CSS styles,
      initial transform will be calculated to `translate(-50%, -16px)`
    -->
    <transition-slide :offset="[0, -16]">
      <div class="block__dropdown" v-if="isVisible">
        ...
      </div>
    </transition-slide>
  </div>
</template>

<style>
  .block {
    position: relative;
  }

  .block__dropdown {
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
  }
</style>

個別プロップスoffset


TransitionScale

要素のtransform: scale()を操作するトランジション。
デフォルトでは、要素をscale(1)からscale(0)にスケールしますが、この動作は:scaleプロップスでカスタマイズできます。
axisプロップスを介して、さまざまな軸で動作します。

個別プロップスscaleaxisorigin

コードの例を表示
<template>
  <!--
    This element appears in `x` axis and disappears in `y`
  -->
  <transition-scale :axis="{ enter: 'x', leave: 'y' }"></transition-scale>

  <!--
    This element behaves like the `transition-expand`,
    but touches only `transform` property
  -->
  <transition-scale transform-origin="50% 0%"></transition-scale>

  <!--
    This element scales just a little when fading in/out.
  -->
  <transition-scale :scale=".8"></transition-scale>

</template>

プロップス

共通プロップス

これらのプロパティは、各トランジションに関連付けられています。

group

コンポーネントをtransition-groupコンポーネントにするかどうか。

export type TransitionGroup = boolean; // Default: false

<template>
  <div>
    <!--
      To animate a list of items, use `group` prop.
      ⚠️ Don't forget you should pass the `:key` to each item in this case.
    -->
    <transition-fade group>
      <div v-for="item in items" :key="item.id">...</div>
    </transition-fade>
  </div>
</template>
tag

transition-groupコンポーネントを使用する場合のトランジションタグ。

export type TransitionTag = string; // Default: 'span'

<template>
  <div>
    <!--
      Passing the tag renders transition component with it.
      It's suitable, for example, for rendering semantic lists:
    -->
    <transition-fade group tag="ul">
      <li v-for="item in items" :key="item.id">...</li>
    </transition-fade>

    <!-- ✨ Rendered HTML: -->
    <ul>
      <li>...</li>
      <li>...</li>
    </ul>
  </div>
</template>
appear

ノードの最初のレンダリング時にトランジションを適用するかどうか。元のVueトランジションのappearプロップスとまったく同じように機能します。

export type TransitionAppear = boolean; // Default: undefined

<template>
  <div>
    <!--
      This element appears when mounted if `isVisible` is `true` by default.
    -->
    <transition-fade appear>
      <div v-if="isVisible">...</div>
    </transition-fade>
  </div>
</template>
mode

トランジションモード.

export type TransitionMode = 'in-out' | 'out-in' | undefined; // Default: undefined

<template>
  <div>
    <!--
      Current element transitions out first, then when complete,
      the new element transitions in.
    -->
    <transition-slide mode="out-in">
      <component :is="currentComponent">...</component>
    </transition-slide>
  </div>
</template>
duration

トランジションアニメーションの期間(ミリ秒)。
オブジェクトが指定されている場合、enterleaveの値がそれぞれエンタートランジションとリーヴトランジションに使用されます。

// Default: 300
export type TransitionDuration = number | { enter: number, leave: number }

<template>
  <div>
    <!--
      If single value provided, the passed amount of milliseconds
      applied to enter and leave animations both.
      This element will appear and disappear within 500ms:
    -->
    <transition-fade :duration="500">
      <div v-if="isVisible">...</div>
    </transition-fade>

    <!--
      If an object given, it SHOULD have `enter` and `leave` keys.
      This element appears in 200ms and disappears within 500ms:
    -->
    <transition-fade :duration="{ enter: 200, leave: 500 }">
      <div v-if="isVisible">...</div>
    </transition-fade>
  </div>
</template>
move-duration

transition-groupを使用する場合、要素の位置変更のアニメーション期間(ミリ秒)。

Vueにはプロップスを介して移動アニメーションの期間を設定するネイティブな方法はありませんが、CSSカスタムプロパティを使用してこのタスクを実行できます。

👀 説明を表示
<!-- This way it can be set dynamically -->
<div style="--move-duration: 300ms;">
  <div class="scale-move"></div>
  <div class="scale-move"></div>
</div>
```

```css
.scale-move {
  transition-duration: var(--move-duration, 300ms);
}
```

</details>

```ts
// Default: 300
export type TransitionMoveDuration = number;
delay

トランジションアニメーションの遅延(ミリ秒)。
オブジェクトが指定されている場合、enterleaveの値がそれぞれエンタートランジションとリーヴトランジションに使用されます。

// Default: 300
export type TransitionDelay = number | { enter: number, leave: number };

<template>
  <div>
    <!--
      If single value provided, then enter and leave animations will wait
      for given amount of milliseconds before run.
      This element will appear and disappear 100ms after
      `isVisible` property changes:
    -->
    <transition-fade :delay="100">
      <div v-if="isVisible">...</div>
    </transition-fade>

    <!--
      If an object given, it SHOULD have `enter` and `leave` keys.
      This element appears immediately and disappears 200ms after
      `isVisible` property changes:
    -->
    <transition-fade :duration="{ enter: 0, leave: 300 }">
      <div v-if="isVisible">...</div>
    </transition-fade>
  </div>
</template>
easing

トランジションアニメーションのイージング。有効なCSSトランジションタイミング関数である必要があります。
オブジェクトが指定されている場合、enterleaveの値がそれぞれエンタートランジションとリーヴトランジションに使用されます。

export type TransitionEasing = string; // Default: 'cubic-bezier(.25, .8, .5, 1)'

<template>
  <div>
    <!--
      If single value provided, then enter and leave animations will use it:
    -->
    <transition-fade easing="ease-out">
      <div v-if="isVisible">...</div>
    </transition-fade>

    <!--
      If an object given, it SHOULD have `enter` and `leave` keys.
      This element uses custom animation known as `bounce-in` for entering
      and simple `ease-out` curve for leaving:
    -->
    <transition-fade
      :easing="{
        enter: 'cubic-bezier(0.6, 0, 0.4, 2)',
        leave: 'ease-out'
      }"
    >
      <div v-if="isVisible">...</div>
    </transition-fade>
  </div>
</template>
no-opacity

要素のopacityをアニメーション化しないようにするかどうか。

デフォルトでは、各トランジションはメインプロパティに加えてopacityを操作します。
ただし、これは常に必要とは限りません。たとえば、画面の端から表示されるモーダルパネルを実装する場合などです。

このプロップスは明らかにtransition-fadeコンポーネントには適用できません。

export type TransitionNoOpacity = boolean; // Default: false

<template>
  <div>
    <!--
      This panel appears from the right edge of the screen,
      while its transparency remains unchanged.
    -->
    <transition-slide :offset="['100%', 0]" no-opacity>
      <div class="panel" v-if="isVisible">...</div>
    </transition-slide>
  </div>
</template>

<style>
  .panel {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    background: #ffffff;
    width: 400px;
  }
</style>
no-move

transition-groupを使用する場合、要素の位置変更のアニメーション化を行わないようにするかどうか。

デフォルトでは、groupモードを使用する場合、要素が削除されると、残りの要素はスムーズに位置を変更します。
絶対位置指定が与えられ、フローから外れるため、親コンテナの高さが縮小されます。

通常は問題ありませんが、transition-expandと順番に配置された要素を互いに重ねて使用する場合など、粗く見える場合があります。
このオプションを使用すると、このような状況でより快適な要素の動作を実現できます。

export type TransitionNoMove = boolean; // Default: false

<template>
  <div>
    <!--
      In this case, the height of the parent element (`ul`) changes smoothly.
    -->
    <transition-expand group no-move tag="ul">
      <li v-for="item in items" :key="item.id">...</li>
    </transition-expand>
  </div>
</template>

TransitionExpandの個別プロップス

axis

要素を展開する軸。
オブジェクトが指定されている場合、enterleaveの値がそれぞれエンタートランジションとリーヴトランジションに使用されます。

type ExpandAxisValue = 'x' | 'y'; // Default: 'y'
export type TransitionExpandAxis = ExpandAxisValue | { enter: ExpandAxisValue, leave: ExpandAxisValue }

TransitionSlideの個別プロップス

offset

x軸とy軸による、トランジション前後の要素のオフセット。
整数またはパーセンテージ値の文字列表現(例:'100%')である必要があります。

数値はpxオフセットとして扱われ、%記号で終わる文字列値は要素の幅/高さのパーセンテージとして扱われます。
例と説明

オブジェクトが指定されている場合、enterleaveの値がそれぞれエンタートランジションとリーヴトランジションに使用されます。

type SlideOffsetValue = [number | string, number | string];

// Default: [0, -16]
export type TransitionSlideOffset = SlideOffsetValue | { enter: SlideOffsetValue, leave: SlideOffsetValue }

TransitionScaleの個別プロップス

axis

アニメーション化するスケール軸。

* `both` (uses `transform: scale()`)
* `x` (uses `transform: scaleX()`)
* `y` (uses `transform: scaleY()`)

例と説明

オブジェクトが指定されている場合、enterleaveの値がそれぞれエンタートランジションとリーヴトランジションに使用されます。

type ScaleAxisValue = 'x' | 'y' | 'both';

// Default: 'both'
export type TransitionScaleAxis = ScaleAxisValue | { enter: ScaleAxisValue, leave: ScaleAxisValue }
origin

要素に適用されるtransform-origin CSSプロパティ。

オブジェクトが指定されている場合、enterleaveの値がそれぞれエンタートランジションとリーヴトランジションに使用されます。

例と説明

オブジェクトが指定されている場合、enterleaveの値がそれぞれエンタートランジションとリーヴトランジションに使用されます。

// Default: '50% 50%'
export type TransitionScaleAxis = string | { enter: string, leave: string }
scale

トランジション前後の要素のスケール値。01の間の数値である必要があります。

オブジェクトが指定されている場合、enterleaveの値がそれぞれエンタートランジションとリーヴトランジションに使用されます。

例と説明

オブジェクトが指定されている場合、enterleaveの値がそれぞれエンタートランジションとリーヴトランジションに使用されます。

// Default: 0
export type TransitionScaleScale = number | { enter: number, leave: number }

イベント

コンポーネントは特別なイベントを提供しませんが、標準のトランジションイベントをすべてトリガーします。

  • before-enter
  • enter
  • after-enter
  • enter-cancelled
  • before-leave
  • leave
  • after-leave
  • enter-leave