【Vue × Splide.js】レスポンシブなカルーセルコンポーネントの実装

最近、Vue.js を使って Splide.js を活用し、レスポンシブなカルーセルコンポーネントを作成しました。この投稿では、その実装プロセスを詳しく紹介するとともに、au Ponta Portal の新しいカルーセルコンポーネント「au PAY マーケットでつかう・ためる」についても紹介したいと思います。

## au Ponta Portal の新カルーセル機能
このたび、au Ponta Portal で新たに実装・リリースした「au PAY マーケットでつかう・ためる」は、ユーザーが Ponta ポイントを簡単に活用・獲得できるキャンペーン情報をスライド形式で表示する便利なコンポーネントです。

特徴として：
・直感的な操作性：矢印ボタンやスライド操作でスムーズに移動可能。
・レスポンシブデザイン：スマートフォン、タブレット、PC の各デバイスに最適化。
・Ponta ポイントの魅力的なプロモーション：キャンペーン情報を強調表示。
以下の画像は、この新コンポーネントの実際の画面です。

![スクリーンショット 2024-12-03 19.13.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951569/3e639c11-4469-9457-419e-ffa6538872be.png)

## Splide.js を使ったカルーセル実装のステップ
1. 必要なライブラリをインストール
プロジェクトに Splide.js を追加します：

```
npm install @splidejs/splide
```

## 2. Vue コンポーネントの構造
以下は Vue.js で作成したカルーセルコンポーネントのテンプレートコードです：

```
<template>
  <div class="article-splide">
    <div class="splide" ref="splideRef">
      <template v-if="isArrows">
        <div class="splide__arrows">
          <button class="splide__arrow splide__arrow--prev">
            <img src="sample_prev.svg" alt="前へ" />
          </button>
          <button class="splide__arrow splide__arrow--next">
            <img src="sample_next.svg" alt="次へ" />
          </button>
        </div>
      </template>
      <ul class="splide__pagination"></ul>
      <div class="splide__track">
        <ul class="splide__list">
          <template v-for="(item, index) in carouselItem" :key="item.url">
            <li class="splide__slide">
              <div class="splide-item">
                <a :href="item.url">
                  <img :src="item.image" :alt="item.alt" />
                  <div v-if="titleFlg" class="splide-text">
                    <p>{{ item.title }}</p>
                  </div>
                </a>
              </div>
            </li>
          </template>
        </ul>
      </div>
    </div>
  </div>
</template>
```

Vueコンポーネントのtemplate部分では、カルーセルのUI構造が定義されています。以下は主要な要素の説明です：

```<section class="splide">```
カルーセル全体を囲むコンテナ。
Splide.jsで指定されたCSSクラスsplideを持ち、Splideライブラリがこのコンテナを操作します。

```<div class="splide__arrows">```
左右の矢印ボタンを表示するコンテナ。
矢印ボタンは次のように定義されています：
```splide__arrow--prev```: 前のスライドへ移動するボタン。
```splide__arrow--next```: 次のスライドへ移動するボタン。

```<div class="splide__track">```
スライドをラップする要素。
Splide.jsでトラック(スライドの動く部分)として認識されます。

```<ul class="splide__list">```
個々のスライドアイテムを配置するリスト。

スライド要素は```<li class="splide__slide">```で定義され、以下のような内容を含みます：
　・画像 (```<img>```): スライドのメインコンテンツ。
　・リンク (```<a>```): ユーザーがクリック可能なリンク。

```<ul class="splide__pagination">```
スライド位置を示すページネーション用のドット。
Splide.jsが自動で生成します。

## 3. Splide.js を初期化するロジック
以下のコードで Splide インスタンスを設定します：
```
import { Splide } from '@splidejs/splide';
import '@splidejs/splide/dist/css/themes/splide-default.min.css';
import { onMounted, ref } from 'vue';

export default {
  name: 'Carousel',
  props: {
    carouselItem: Array,
    carouselFlag: Boolean,
    titleFlg: Boolean,
    carouselId: String,
    carouselRole: String,
  },
  setup(props) {
    const splideRef = ref(null);
    const isArrows = props.carouselItem.length > 1;

    const initSplide = () => {
      new Splide(splideRef.value, {
        type: 'loop',
        perPage: 3,
        gap: '16px',
        arrows: isArrows,
        pagination: isArrows,
        breakpoints: {
          959: { perPage: 2 },
        },
      }).mount();
    };

    onMounted(() => {
      if (props.carouselFlag) {
        initSplide();
      }
    });

    return { splideRef, isArrows };
  },
};
```
この部分では、Vueのsetup関数を使い、以下の処理を行っています：
1. Splideインスタンスの初期化
Splide.jsを用いてカルーセルを制御します。
コンポーネントのマウント時に、カルーセルが正しく動作するように初期化コードをonMountedで設定。

2. Splide 設定項目
```type```: 'loop': カルーセルが無限ループするよう設定。
```perPage```: 表示するスライド数を指定 (例: デフォルトは3枚)。
```breakpoints```: デバイス幅に応じたレスポンシブ設定。画面が小さい場合、表示スライド数を自動的に調整。
```pagination```: true: ページネーション(ドット)の表示を有効化。

3. 条件付き表示の処理
矢印やページネーションを、スライド数に応じて表示/非表示にする処理を組み込む。

## 4. カスタムスタイル
以下は SCSS を使ったスタイル例です：
```
.splide {
  max-width: 480px;
  margin: auto;

  &__slide {
    border-radius: 8px;
    overflow: hidden;
    img {
      width: 100%;
    }
  }

  &__arrows {
    display: flex;
    justify-content: space-between;
    button {
      background: #fff;
      border-radius: 50%;
    }
  }

  &__pagination {
    display: flex;
    justify-content: center;
    li {
      width: 8px;
      height: 8px;
      background: #ccc;
      &.is-active {
        background: #000;
      }
    }
  }
}
```
SCSSを使用してスタイルを定義。
主なカスタマイズポイント：
　1. カルーセル全体のデザイン：最大幅480pxに設定し、中央に配置。
　2. スライドアイテム：角丸デザインと画像の完全表示を実現。
　3. 矢印ボタン：丸い背景で直感的に操作可能。
　4. ページネーション：現在のスライド位置を示すドットの色変更。

## まとめ
今回、Vue と Splide.js を使ってレスポンシブなカルーセルコンポーネントを作成しました。実装を通じて以下の点が学べました：

動的データの扱い：Vue の props を活用して動的にアイテムをレンダリング。
ライブラリの活用：Splide.js を使うことで、簡単にスライダー機能を実装。
レスポンシブデザイン：breakpoints を設定してデバイス幅に応じた表示を実現。
さらに、au Ponta Portal の「au PAY マーケットでつかう・ためる」は、Splide.js を活用した参考例として、実用性とデザイン性の両立を目指したプロジェクトとなっています。

この記事が少しでもお役に立てれば幸いです！