🎃

【Vue】AutoAnimate使って超簡単にアニメーションつけてみた

2024/02/09に公開

AutoAnimate とは?

FormKit が提供するアニメーションライブラリ。
ライブラリをインストールすると簡単に使えるすごいやつ。
Vue、React、Preact、Solid、Svelta、Angular、NativeJS に対応してますが、この記事では Vue で触っていきます。

設定

  1. 初めにインストール
npm install @formkit/auto-animate
  1. 次に config に追記
nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@formkit/auto-animate/nuxt'],
})
  1. 最後に animation させたい親要素に v-auto-animate をつけるだけ
<div v-auto-animate>
// この中の子要素がアニメーション付与される
</div>

できること

子要素が追加、削除、移動した時にアニメーションを簡単につけられる。
個人的に下記が感動した。
以下 DEMO とサンプル

  • DEMO
サンプルコード
<script setup>
import { ref } from "vue";

const items = ref(["React", "Vue", "Svelte", "Angular"]);

function sortAsc() {
  items.value.sort();
}
function sortDesc() {
  items.value.sort().reverse();
}
</script>

<template>
  <div>
    <div>
      <button @click="sortAsc">Sort A-Z ↑</button>
      <button @click="sortDesc">Sort Z-A ↓</button>
    </div>
    <ul v-auto-animate>
      <li v-for="item in items" :key="item">
        {{ item }}
      </li>
    </ul>
  </div>
</template>

ちょっと gif は早すぎてわかりずらいが、興味があれば実際に公式ドキュメント内でサンプルを触ってみるとわかりやすい。
v-auto-animate を親要素に指定するだけで簡単に animation を設定できる他に、composable に option を直接渡せるのも個人的に使いやすいなって思った。
css や js を書く手間を省いて簡単に動的な要素に animation をつけられるのは本当に素晴らしい!

ちょっと検証

  • あくまで動的に動く要素の親要素に設定しないと反映されない
NG サンプル
<script setup>
import { ref } from "vue";

// 並べ替え
const sortItems = ref(["React", "Vue", "Svelte", "Angular"]);
function sortAsc() {
  sortItems.value.sort();
}
function sortDesc() {
  sortItems.value.sort().reverse();
}

// 消す
const removeItems = ref(["1", "2", "3", "4", "5"]);
function removeItem(toRemove) {
  removeItems.value = removeItems.value.filter(
    (removeItems) => removeItems !== toRemove
  );
}
</script>

<template>
  <div>
    <button @click="sortAsc">Sort A-Z ↑</button>
    <button @click="sortDesc">Sort Z-A ↓</button>
  </div>
  <div v-auto-animate>
    <ul>
      <li v-for="item in sortItems" :key="item">
        {{ item }}
      </li>
    </ul>
    <h5>Click emojis to remove them.</h5>
    <ul>
      <li v-for="item in removeItems" :key="item" @click="removeItem(item)">
        {{ item }}
      </li>
    </ul>
  </div>
</template>
  • 親要素には個別に v-auto-animate つける必要がある
OK サンプル
<script setup>
import { ref } from "vue";

// 並べ替え
const sortItems = ref(["React", "Vue", "Svelte", "Angular"]);
function sortAsc() {
  sortItems.value.sort();
}
function sortDesc() {
  sortItems.value.sort().reverse();
}

// 消す
const removeItems = ref(["1", "2", "3", "4", "5"]);
function removeItem(toRemove) {
  removeItems.value = removeItems.value.filter(
    (removeItems) => removeItems !== toRemove
  );
}
</script>

<template>
  <div>
    <button @click="sortAsc">Sort A-Z ↑</button>
    <button @click="sortDesc">Sort Z-A ↓</button>
  </div>
  <div>
    <!-- 個別につける -->
    <ul v-auto-animate>
      <li v-for="item in sortItems" :key="item">
        {{ item }}
      </li>
    </ul>
    <h5>Click emojis to remove them.</h5>
    <!-- 個別につける -->
    <ul v-auto-animate>
      <li v-for="item in removeItems" :key="item" @click="removeItem(item)">
        {{ item }}
      </li>
    </ul>
  </div>
</template>
  • useAutoAnimation は下記の引数 をとることができる
    disrespectUserMotionPreference は非推奨だが設定はできる
useAutoAnimation 引数
const [parent] = useAutoAnimate({
  duration: 1000,
  easing: "ease-in",
  disrespectUserMotionPreference: true,
});
  • 動的に変わる要素のなかに、動的に変わる要素があれば下記のように設定可能
サンプルコード
<script setup>
import { ref } from "vue";
import { useAutoAnimate } from "@formkit/auto-animate/vue";

const isOpen = ref(false);
const menuItems = ref(["menu1", "menu2", "menu3"]);
const [parent] = useAutoAnimate({
  duration: 1000,
  easing: "ease-in",
  disrespectUserMotionPreference: true,
});

const toggleOpen = () => {
  isOpen.value = !isOpen.value;
};

const sortAsc = () => {
  menuItems.value.sort();
};
const sortDesc = () => {
  menuItems.value.sort().reverse();
};
</script>

<template>
  <div>
    <button @click="toggleOpen">toggle menu</button>
    <button @click="sortAsc">Sort ↑</button>
    <button @click="sortDesc">Sort ↓</button>
  </div>
  <!-- div全体に設定 -->
  <div v-auto-animate>
    <!-- ulには別途設定 -->
    <ul v-if="isOpen" ref="parent" class="menu">
      <li v-for="item in menuItems" :key="item">
        {{ item }}
      </li>
    </ul>
  </div>
</template>

<style scoped>
.menu {
  height: 200px;
  background: #dcdcdc;
  width: 200px;
}
</style>

まとめ

動的に追加、移動、削除された要素は一見わかりづらいが アニメーションをつけると視覚的に変化したのがわかりやすくなる。(css とか js でやると結構面倒だったりする)
AutoAnimate の導入コストはかなり低いのでどんどん使っていきたい!

Discussion