アニメーション(複数)

記事の内容

概要

transition-groupは、リストアイテムの追加・削除や順序変更に対してアニメーションを適用するために使用されます。

list

フェードイン・フェードアウト、スライドイン・スライドアウト、スケール、回転などのアニメーションが適用されます。

list
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>リッチなトランジショングループアニメーション</title>
    <link rel="stylesheet" href="main.css" />
  </head>
  <body class="app-body">
    <div id="app" class="app-container">
      <button @click="addItem" class="btn">追加</button>
      <button @click="removeItem" class="btn">削除</button>
      <transition-group name="list" tag="p">
        <span v-for="item in items" :key="item" class="list-item">
          {{ item }}
        </span>
      </transition-group>
    </div>

    <!-- CDN -->
    <script src="CDNのURL"></script>
    <script src="main.js"></script>
  </body>
</html>
Vue.createApp({
  data() {
    return {
      items: [1, 2, 3, 4, 5],
    };
  },
  methods: {
    addItem() {
      this.items.push(this.items.length + 1);
    },
    removeItem() {
      this.items.pop();
    },
  },
}).mount("#app");
.app-body {
  font-family: Arial, sans-serif;
  background-color: #f4f4f9;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  margin: 0;
}

.app-container {
  text-align: center;
}

.btn {
  padding: 10px 20px;
  margin: 10px;
  background-color: #3498db;
  border: none;
  border-radius: 5px;
  color: white;
  cursor: pointer;
  font-size: 16px;
}

.btn:hover {
  background-color: #2980b9;
}

.list-item {
  display: inline-block;
  margin: 10px;
  padding: 20px;
  background-color: #fff;
  border-radius: 10px;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
  transition: all 0.5s;
}

/* フェードイン・フェードアウト */
.list-enter-active,
.list-leave-active {
  transition: opacity 0.5s, transform 0.5s;
}
.list-enter-from,
.list-leave-to {
  opacity: 0;
  transform: translateY(30px) scale(0.5) rotateY(180deg);
}

/* スライドイン・スライドアウト */
.list-enter-active,
.list-leave-active {
  transition: transform 0.5s;
}
.list-enter-from,
.list-leave-to {
  transform: translateX(30px);
}

/* バウンスアニメーション */
.list-move {
  transition: transform 0.5s;
}
出力結果
{{ item }}

flip-list

リストアイテムがY軸で回転して表示され、動的で視覚的に魅力的です。

flip-list
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>リッチなトランジショングループアニメーション</title>
    <link rel="stylesheet" href="main.css" />
  </head>
  <body class="app-body">
    <div id="app" class="app-container">
      <button @click="addItem" class="btn">追加</button>
      <button @click="removeItem" class="btn">削除</button>
      <transition-group name="flip-list" tag="p">
        <span v-for="item in items" :key="item" class="list-item">
          {{ item }}
        </span>
      </transition-group>
    </div>

    <!-- CDN -->
    <script src="CDNのURL"></script>
    <script src="main.js"></script>
  </body>
</html>
Vue.createApp({
  data() {
    return {
      items: [1, 2, 3, 4, 5],
    };
  },
  methods: {
    addItem() {
      this.items.push(this.items.length + 1);
    },
    removeItem() {
      this.items.pop();
    },
  },
}).mount("#app");
.app-body {
  font-family: Arial, sans-serif;
  background-color: #f4f4f9;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  margin: 0;
}

.app-container {
  text-align: center;
}

.btn {
  padding: 10px 20px;
  margin: 10px;
  background-color: #3498db;
  border: none;
  border-radius: 5px;
  color: white;
  cursor: pointer;
  font-size: 16px;
}

.btn:hover {
  background-color: #2980b9;
}

.list-item {
  display: inline-block;
  margin: 10px;
  padding: 20px;
  background-color: #fff;
  border-radius: 10px;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
  transition: all 0.5s;
}

/* Flip List アニメーション */
.flip-list-enter-active,
.flip-list-leave-active {
  transition: all 0.5s;
}
.flip-list-enter-from,
.flip-list-leave-to {
  transform: rotateY(180deg);
  opacity: 0;
}

/* バウンスアニメーション */
.flip-list-move {
  transition: transform 0.5s;
}
出力結果
{{ item }}

list-complete

リストアイテムの追加、削除、並べ替え時に滑らかな移動アニメーションが適用されます。

list-complete
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>リッチなトランジショングループアニメーション</title>
    <link rel="stylesheet" href="main.css" />
  </head>
  <body class="app-body">
    <div id="app" class="app-container">
      <button @click="addItem" class="btn">追加</button>
      <button @click="removeItem" class="btn">削除</button>
      <transition-group name="list-complete" tag="p">
        <span v-for="item in items" :key="item" class="list-item">
          {{ item }}
        </span>
      </transition-group>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@3.2.31/dist/vue.global.prod.js"></script>
    <script src="main.js"></script>
  </body>
</html>
Vue.createApp({
  data() {
    return {
      items: [1, 2, 3, 4, 5],
    };
  },
  methods: {
    addItem() {
      this.items.push(this.items.length + 1);
    },
    removeItem() {
      this.items.pop();
    },
  },
}).mount("#app");
.app-body {
  font-family: Arial, sans-serif;
  background-color: #f4f4f9;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  margin: 0;
}

.app-container {
  text-align: center;
}

.btn {
  padding: 10px 20px;
  margin: 10px;
  background-color: #3498db;
  border: none;
  border-radius: 5px;
  color: white;
  cursor: pointer;
  font-size: 16px;
}

.btn:hover {
  background-color: #2980b9;
}

.list-item {
  display: inline-block;
  margin: 10px;
  padding: 20px;
  background-color: #fff;
  border-radius: 10px;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
  transition: all 0.5s;
}

/* List Complete アニメーション */
.list-complete-enter-active,
.list-complete-leave-active {
  transition: all 0.5s;
}
.list-complete-enter-from,
.list-complete-leave-to {
  transform: translateY(30px);
  opacity: 0;
}

/* Move animation for sorting */
.list-complete-move {
  transition: transform 0.5s;
}
出力結果
{{ item }}

staggered-fade

各アイテムが順番にフェードイン・フェードアウトしながら表示されます。

staggered-fade
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>リッチなトランジショングループアニメーション</title>
    <link rel="stylesheet" href="main.css" />
  </head>
  <body class="app-body">
    <div id="app" class="app-container">
      <button @click="addItem" class="btn">追加</button>
      <button @click="removeItem" class="btn">削除</button>
      <transition-group name="staggered-fade" tag="p">
        <span v-for="item in items" :key="item" class="list-item">
          {{ item }}
        </span>
      </transition-group>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@3.2.31/dist/vue.global.prod.js"></script>
    <script src="main.js"></script>
  </body>
</html>
Vue.createApp({
  data() {
    return {
      items: [1, 2, 3, 4, 5],
    };
  },
  methods: {
    addItem() {
      this.items.push(this.items.length + 1);
    },
    removeItem() {
      this.items.pop();
    },
    updateIndexes() {
      this.$el.querySelectorAll(".list-item").forEach((el, index) => {
        el.style.setProperty("--index", index);
      });
    },
  },
  mounted() {
    this.$nextTick(() => {
      this.updateIndexes();
    });
  },
  updated() {
    this.updateIndexes();
  },
}).mount("#app");
.app-body {
  font-family: Arial, sans-serif;
  background-color: #f4f4f9;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  margin: 0;
}

.app-container {
  text-align: center;
}

.btn {
  padding: 10px 20px;
  margin: 10px;
  background-color: #3498db;
  border: none;
  border-radius: 5px;
  color: white;
  cursor: pointer;
  font-size: 16px;
}

.btn:hover {
  background-color: #2980b9;
}

.list-item {
  display: inline-block;
  margin: 10px;
  padding: 20px;
  background-color: #fff;
  border-radius: 10px;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
  transition: all 0.5s;
}

/* Staggered Fade アニメーション */
.staggered-fade-enter-active,
.staggered-fade-leave-active {
  transition: opacity 0.5s ease-in-out, transform 0.5s ease-in-out;
}
.staggered-fade-enter-from,
.staggered-fade-leave-to {
  opacity: 0;
  transform: translateY(30px);
}

.staggered-fade-enter-active .list-item {
  transition-delay: calc(0.1s * var(--index));
}

.staggered-fade-leave-active .list-item {
  transition-delay: calc(0.1s * var(--index));
}
出力結果
{{ item }}
記事の内容
閉じる