1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Vue.jsでスライドショーを自作

Posted at

Vue.jsの勉強中でスライドショーを自作したので自分用のメモ
カスタムイベントtransitionendを定義して終了時に再度setIntervalを実行。

<div id="top_slide">
    <div class="sliderpro_wrap">
      <div class="sliderpro_main" ref="getParentWidth">
        <ul :style="{width:containerW * itemsCount + 'px',transform: `translateX(${sliderTransform}px)`}"
          v-transitionend="slideInterval" @touchstart="touchstart" @touchmove="touchMove" @touchend="touchEnd">
          <li v-for="item in items" :key="item.id" :style="{width:containerW + 'px'}"><img :src="item.src"></li>
        </ul>

        <div class="sliderpro_arrows">
          <div class="sliderpro_arrow sliderpro_arrow_prev" v-on:click="onClickPrev"></div>
          <div class="sliderpro_arrow sliderpro_arrow_next" v-on:click="onClickNext"></div>
        </div>
      </div>

      <div class="sliderpro_thumbnails">
        <ul>
          <li v-for="(item,index) in items" :key="item.id" v-on:click="onClickThumbnal(index)"
            :class="{ active: item.activeClass}"><img :src="item.src"></li>
        </ul>
      </div>
    </div>
  </div>
const top_slide = Vue.createApp({
    data: function () {
      return {
        // カルーセル画像の配列
        items: [
          {
            id: 1,
            src: "img/slide/img_01.jpg"
          },
          {
            id: 2,
            src: "img/slide/img_02.jpg"
          },
          {
            id: 3,
            src: "img/slide/img_03.jpg"
          }
        ],
        sliderTransform:0,
        selectedIndex: 0,
        containerW:0,
        timer:false,
        startX:0,
        moveX:0,
      }
    },
    mounted () {
      this.initFunc();
      // 要素の幅を取得するメソッド
      this.getTargetWidth();
      // ユーザーがウィンドウサイズを変更したら実行されるようにする
      window.addEventListener('resize', this.getTargetWidth)
    },
    beforeDestroy(){
      //コンポーネントが破棄されたとき
      this.slideStopInterval();
    },
    computed: {
      itemsCount:function(){
        return this.items.length
      }
    },
    methods:{
      initFunc:function(){
        this.onClickThumbnal(this.selectedIndex);
        this.slideInterval();
      },
      getTargetWidth(){
        this.containerW = this.$refs.getParentWidth.clientWidth;
        this.sliderTransform = -(this.containerW * this.selectedIndex);
      },
      onClickPrev:function(){
        this.selectedIndex < 1 ? this.selectedIndex = this.itemsCount -1:  this.selectedIndex -= 1;
        this.onClickThumbnal(this.selectedIndex);
      },
      onClickNext:function(){
        this.selectedIndex < this.itemsCount - 1 ? this.selectedIndex += 1 :  this.selectedIndex = 0;
        this.onClickThumbnal(this.selectedIndex);
      },
      onClickThumbnal:function(index){
      this.slideStopInterval(); //スライド一旦停止
      this.selectedIndex = index;
       this.sliderTransform = -(this.containerW * index);
       this.items.filter(function(value,f_index,array){
        //activeClass切り替え
        return f_index === index ? value.activeClass = true: value.activeClass = false
       });
      },
      slideInterval:function(){
        this.timer = setInterval(function(){
          this.onClickNext();
        }.bind(this),4000);
      },
      slideStopInterval(){
        if(this.timer){
          clearInterval(this.timer);
          this.timer = 0;
        }
      },
      touchstart(e){
        this.slideStopInterval();
        this.startX = e.touches[0].pageX;
      },
      touchMove(e){
        this.moveX = e.touches[0].pageX - this.startX
      },
      touchEnd(){
        if(this.moveX > 10){
         this.onClickPrev();
          //右スワイプ
        }else if(this.moveX < -10){
          //左スワイプ
          this.onClickNext();
        }
        this.slideStopInterval();
      }
    }
  });
  top_slide.directive('transitionend', {
    mounted(el,binding) {
      el.addEventListener('transitionend', () => {
        binding.value();
      });
  }
});

top_slide.mount("#top_slide");
.sliderpro_wrap{
    position: relative;
    max-width: 1400px;
    margin: 0 auto;
}
.sliderpro_wrap .sliderpro_main{
    overflow: hidden;
    position: relative;
    margin-bottom: 10px;
}
.sliderpro_wrap .sliderpro_main ul{
    transition: transform 1.1s ease-in-out;
}
.sliderpro_wrap .sliderpro_main ul > li{
    float: left;
}
.sliderpro_wrap img{
    width: 100%;
}

.sliderpro_wrap .sliderpro_thumbnails ul{
   letter-spacing: -0.5em;
   text-align: center;
}
.sliderpro_wrap .sliderpro_thumbnails ul li{
    cursor: pointer;
    display: inline-block;
    letter-spacing: normal;
    vertical-align: top;
    width: 9%;
    margin-right: 1.111%;
}
.sliderpro_wrap .sliderpro_thumbnails ul li:nth-child(10){
    margin-right: 0;
}
.sliderpro_wrap .sliderpro_thumbnails ul li:not(:nth-child(-n + 10)){
    margin-top: 1.1111%;
}
.sliderpro_wrap .sliderpro_thumbnails ul img{
    -webkit-filter: grayscale(100%);
    filter: grayscale(100%);
    transition:filter 0.5s ease-in-out;
}
.sliderpro_wrap .sliderpro_thumbnails ul li.active img,
.sliderpro_wrap .sliderpro_thumbnails ul li:hover img{
    -webkit-filter: grayscale(0%);
    filter: grayscale(0%);
}

/* 矢印ここから */
.sliderpro_wrap .sliderpro_arrows .sliderpro_arrow{
    position: absolute;
    left: 20px;
    top: 50%;
    transform: translateY(-50%) rotate(45deg);
    transform-origin: center center;
    width: 25px;
    height: 25px;
    border-left: 6px solid #fff;
    border-bottom: 6px solid #fff;
    transition: opacity 0.6s ease-in-out;
    cursor: pointer;
}
.sliderpro_wrap .sliderpro_arrows .sliderpro_arrow.sliderpro_arrow_next{
    transform: translateY(-50%) rotate(-135deg);
    left: auto;
    right: 20px;
}
.sliderpro_wrap .sliderpro_arrows .sliderpro_arrow:hover{
    opacity: 0.7;
}


@media screen and (max-width:767px) {
    .sliderpro_wrap .sliderpro_arrows .sliderpro_arrow{
        width: 15px;
        height: 15px;
        border-width: 3px;
    }
}
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?