记录

197 阅读2分钟

网上参考别人的代码改动的,原链接忘记是啥了,写这记一下(如果不妥,请评论说下)

<template>
  <div class="swiper" ref="swiper" @click.prevent="handleClick">
    <div
        class="swiper-list"
        :style="{width: swiperListWidth + 'px', transform: 'translateX(' + translateX + 'px)', transitionDuration: transitionDuration + 's' }"
        ref="swiperList"
    >
      <div v-for="(item, i) in imgUrlList"
           :style="{backgroundColor: item}"
           :key="i"
           :class="index === i ? 'current-item swiper-item' : 'swiper-item'"
           @click="see(i)"
      >
        <img :src="item.url" alt="">
      </div>
    </div>
    <!--<div class="dot">-->
          <!--<span-->
              <!--v-for="(x, i) in sum" :key="'dot' + x"-->
              <!--:style="{background: i ===  index ? indicatorColor : 'rgba(255, 255, 255, .5)'}"-->
              <!--:class="[i === index ? 'on': '']"-->
          <!--&gt;-->
          <!--</span>-->
    <!--</div>-->
    <!--{{index}}-->
  </div>
</template>
<script>
export default {
  name: 'Test',
  data () {
    return {
      swiperWidth: '', // 轮播图盒子的宽度
      index: this.initialIndex, // 轮播图序号
      sum: 4, // 轮播图片数量
      transitionDuration: 0.5, // 切换动画时长
      timer: '', // 定时器
      startX: '', // touchstart的起始x坐标
      offset: '', // move偏移值
      Loop: 0,
      imgList: ['red', 'bisque', 'blueviolet', 'royalblue'],
      imgUrlList: [
        {
          url: 'https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=2534506313,1688529724&fm=26&gp=0.jpg'
        },
        {
          url: 'https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=1208538952,1443328523&fm=26&gp=0.jpg'
        },
        {
          url: 'https://dss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3386247472,87720242&fm=26&gp=0.jpg'
        },
        {
          url: 'https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3252521864,872614242&fm=26&gp=0.jpg'
        }
      ]
    }
  },
  props: {
    duration: {
      type: Number,
      default: 3000
    },
    initialIndex: {
      type: Number,
      default: 1
    },
    indicatorColor: {
      type: String,
      default: '#fff'
    }
  },
  computed: {
    // 轮播图列表的宽度
    swiperListWidth () {
      return this.swiperWidth * this.sum
    },
    // 轮播图列表偏移值
    translateX () {
      return this.index * this.swiperWidth * -1
    }
  },
  created () {
    this.$nextTick(() => {
      let swiper = this.$refs.swiper
      // 获得轮播图的图片数量
      let swiperItems = document.querySelectorAll('.swiper-item')
      this.sum = swiperItems.length
      console.log(this.sum)
      // 为什么不取屏幕宽度,是因为通用性,由外部的盒子决定轮播图的宽
      this.swiperWidth = swiper.offsetWidth
      // this.autoPlay()
      // addEventListener不可以用匿名函数,因为无法解除绑定
      swiper.addEventListener('touchstart', this.touchStart)
      swiper.addEventListener('touchmove', this.touchMove)
      swiper.addEventListener('touchend', this.touchEnd)
    })
  },
  methods: {
    see (i) {
      this.index = i
    },
    autoPlay () {
      this.timer = setInterval(() => {
        let index = this.index + 1
        // 取余数运算,0%5=0,1%5=1,5%5=0,当然用if判断语句也是可以的
        this.index = index % this.sum
        this.$emit('change', this.index)
      }, this.duration)
    },
    touchStart (e) {
      // 只记录第一根手指触发的值
      clearInterval(this.timer)
      this.transitionDuration = 0
      this.startX = e.targetTouches[0].clientX
    },
    touchMove (e) {
      this.offset = this.startX - e.targetTouches[0].clientX
      this.$refs.swiperList.style.transform = `translateX(${this.translateX - this.offset}px)`
    },
    touchEnd () {
      this.transitionDuration = 0.5
      // 计算偏移值四舍五入,如果拖动距离大于等于0.5则换一张轮播图
      let num = Math.round(this.offset / this.swiperWidth)
      let sum = this.index + num
      // 先计算再赋值给this.index避免重复触发计算属性,为什么这里不取余数,是因为又负数出现
      if (sum > this.sum - 1) {
        sum = this.sum - 1
      } else if (sum < 0) {
        sum = 0
      }
      // 解决拖动距离小于一半,index值无变化,无法触发计算属性,主动还原偏移值
      if (sum === this.index) {
        this.$refs.swiperList.style.transform = `translateX(${this.translateX}px)`
      } else {
        this.index = sum
        this.$emit('change', this.index)
      }
      // 解决当第一次手势滑动后,再次点击offset不跟新问题
      this.offset = 0
      // this.autoPlay()
    },
    handleClick (e) {
      e.preventDefault()
      this.$emit('click', this.index)
    }
  },
  // 实例销毁之前,移除绑定事件
  beforeDestroy () {
    let swiper = this.$refs.swiper
    swiper.removeEventListener('touchstart', this.touchStart)
    swiper.removeEventListener('touchmove', this.touchMove)
    swiper.removeEventListener('touchend', this.touchEnd)
  }
}
</script>
<style lang="less" scoped>
  .swiper {
    position: relative;
    width: 100%;
    height: 150px;
    overflow: hidden;

    .swiper-list {
      display: flex;
      align-items: center;
      width: 100%;
      height: 100%;
      transition-property: all;
      transition-timing-function: cubic-bezier(0.18, 0.89, 0.32, 1.28);

      .swiper-item {
        width: 120%;
        height: 80%;
        margin: 0 10px;
        border-radius: 10px;
        border: 1px solid rebeccapurple;
        overflow: hidden;
        img {
          width: 100%;
          height: 100%;
        }
      }
      .current-item {
        width: 95%;
        height: 90%;
      }
    }
    .dot {
      display: flex;
      position: absolute;
      width: 100%;
      margin-top: -15px;
      justify-content: center;
      span {
        @size: 8px;
        width: @size;
        height: @size;
        background-color: rgba(255, 255, 255, .5);
        border-radius: 50%;
        margin-left: 5px;
      }
      .on {
        width: 12px;
        border-radius: 30%;
        transition: width 0.3s linear;
      }
    }
  }
</style>