LoginSignup
2
1

More than 1 year has passed since last update.

【vue-awesome-swiper】サムネイル付きスライダーの実装

Last updated at Posted at 2022-01-16

はじめに

swiperを用いたスライダーの実装の記事はたくさんあったが、
サムネイル画像もスライダーにする実装ばかりでサムネイル画像を固定画像とするものが少なかったので
残しておきます。

環境

  • MacOS
  • yarn 1.22.17
  • node v14.17.1
  • vue 2.6.14
  • vue-awesome-swiper 4.1.1

完成品

以下のようなサムネイル付きスライダーを作成します!
slicer.gig.gif

全体コード

<template>
  <div class="room-swiper">
    <Swiper ref="swiperRef" class="top" :options="swiperOption">
      <SwiperSlide
        v-for="(slider, index) in sliderContents"
        :key="index"
        class="slide"
      >
        <img class="image" :src="slider" />
      </SwiperSlide>
    </Swiper>
    <div class="thumbs">
      <div
        v-for="(thumbs, index) in thumbsContents"
        :key="index"
        class="slide"
        :class="{ '-active': index === activeIndex }"
      >
        <img class="image" :src="thumbs" @click="clickHandler(index)" />
      </div>
    </div>
  </div>
</template>
<script lang="ts">
import { defineComponent, ref } from '@nuxtjs/composition-api';
import SwiperClass from 'swiper';
import { Swiper, SwiperSlide } from 'vue-awesome-swiper';

export default defineComponent({
  components: {
    Swiper,
    SwiperSlide,
  },
  props: {
    sliderContents: {
      type: Array,
      required: true,
    },
  },
  setup() {
    type SwiperModule = typeof Swiper & {
      $swiper: SwiperClass;
      initSwiper: () => void;
    };

    const swiperRef = ref<SwiperModule>();
    const activeIndex = ref<number>(0);

    // 上のスワイパーは画面読み込み時2番目が表示されているため下のサムネイルも初期選択が2番目になるようにしている
    const thumbsContents = [
      ...props.sliderContents.slice(1),
      props.sliderContents[0],
    ];

    const swiperOption = {
      loop: true,
      loopedSlides: 3,
      spaceBetween: 10,
      slidesPerView: 3,
      autoplay: {
        delay: 5000,
        disableOnInteraction: false,
      },
      on: {
        slideChange: () => {
          if (!swiperRef.value || !swiperRef.value.$swiper) return;
          activeIndex.value = swiperRef.value.$swiper.realIndex;
        },
      },
    };

    const clickHandler = (index: number) => {
      if (
        !swiperRef.value ||
        !swiperRef.value.$swiper ||
        !swiperRef.value.$swiper.controller
      )
        return;
      swiperRef.value?.$swiper.slideToLoop(index);
    };

    return {
      swiperRef,
      activeIndex,
      swiperOptionTop,
      clickHandler,
      thumbsContents,
    };
  },
});
</script>

解説

スワイパー部分

propsで受け取ったsliderContents(画像の配列)をv-forで回しています。
また、optionを swiperOptionとして渡しています。
SwiperSwiperSlide の使い方に関しては以下を参考にしてください。
https://github.com/surmon-china/vue-awesome-swiper

<Swiper ref="swiperTop" class="top" :options="swiperOptionTop">
      <SwiperSlide
        v-for="(slider, index) in sliderContents"
        :key="index"
        class="slide"
      >
        <img class="image" :src="slider" />
      </SwiperSlide>
</Swiper>

オプション

オプション一覧

const swiperTop = ref<SwiperModule>();
const activeIndex = ref<number>(0);

const swiperOption = {
      loop: true,
      loopedSlides: 3,
      spaceBetween: 10,
      slidesPerView: 3,
      autoplay: {
        delay: 5000,
        disableOnInteraction: false,
      },
      on: {
        slideChange: () => {
          if (!swiperTop.value || !swiperTop.value.$swiper) return;
          activeIndex.value = swiperTop.value.$swiper.realIndex;
        },
      },
    };

slideChangeオプションを指定することで、画像がスライドする時に発火してくれます。
realIndexにはスライドしている画像のインデックス番号が入ります。

on: {
    slideChange: () => {
      if (!swiperTop.value || !swiperTop.value.$swiper) return;
      activeIndex.value = swiperTop.value.$swiper.realIndex;
     },
},

サムネイル

画像クリック時にclickHandlerを発火させています。
今回はcssを省いていますが、v-forで回しているindex番号とactiveIndexが一致した時にクラスをつけるというイメージです。
そのクラスにopacityを指定すれば、それっぽくなると思います!


 <div class="thumbs">
      <div
        v-for="(thumbs, index) in thumbsContents"
        :key="index"
        class="slide"
        :class="{ '-active': index === activeIndex }"
      >
        <img class="image" :src="thumbs" @click="clickHandler(index)" />
      </div>
    </div>
const clickHandler = (index: number) => {
      if (
        !swiperTop.value ||
        !swiperTop.value.$swiper ||
        !swiperTop.value.$swiper.controller
      )
        return;
       // 引数に指定したスライドに移動させる slideTo というメソッドを使って移動させる。loopの設定をしている場合はslideToLoop を使う
      swiperTop.value?.$swiper.slideToLoop(index);
    };

さいごに

サムネイル画像付きのスライダーはなんかかっこいいですね!!!

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1