《VUE》走马灯组件

<template>
  <!-- 走马灯 -->
  <div class="box">
    <div class="carousel">
      <div class="item" v-for="(v,i) in list" :key="i" @click="open(v)">
        <img :src="v.img" alt="">
        <!-- 走马灯图中自定义内容 -->
        <slot :current="current"></slot>
      </div>
    </div>
    <div class="indicator" v-if="isIndicator">
      <span :class="{'active': current == i}" v-for="(v,i) in list" :key="i" @click="indicatorCheck(i)"></span>
    </div>
    <template v-if="isArrow">
      <div class="arrow_left" @click="arrowNext(1)"></div>
      <div class="arrow_right" @click="arrowNext(2)"></div>
    </template>
  </div>
</template>

<script>
  export default {
    props: {
      // 走马灯列表
      list: {
        type: Array,
        required: true,
        default: () => []
        // { img: require(''), link: '' }
      },
      // 是否显示下方指示点
      isIndicator: {
        type: Boolean,
        default: false
      },
      // 是否显示左右箭头
      isArrow: {
        type: Boolean,
        default: false
      },
      // 自动切换的时间间隔,单位为毫秒
      interval: {
        type: Number,
        default: 3000
      }
    },
    data() {
      return {
        current: 0,   // 当前在第几张图
        indicator: 1,
        timer: null,
      }
    },
    mounted() {
      this.init()
      this.autoRun()
    },
    destroyed() {
      clearInterval(this.timer)
    },
    methods: {
      // 初始化走马灯列表
      init() {
        let carouselDom = document.querySelector('.carousel')
        // 复制第一张图
        let first = carouselDom.firstElementChild.cloneNode(true)
        // 复制最后一张图
        let last = carouselDom.lastElementChild.cloneNode(true)
        // 将第一张图放在末尾
        carouselDom.appendChild(first)
        // 将最后一张图放在第一张
        carouselDom.insertBefore(last, carouselDom.firstElementChild)
        // 设置最后一张复制图为绝对定位
        last.style.position = "absolute"
        last.style.transform = "translateX(-100%)"
      },
      // 走马灯自动运行
      autoRun() {
        const _this = this
        if(_this.indicator >= _this.list.length) {
          _this.indicator = 0
        }
        this.timer = setInterval(() => {
          this.arrowNext(2)
          _this.indicator++
          if(_this.indicator >= _this.list.length) {
            _this.indicator = 0
          }
        }, this.interval)
      },
      // 下方指示器事件
      indicatorCheck(index) {
        let carouselDom = document.querySelector('.carousel')
        let count = this.list.length
        // 当前在最后一张图时,无缝切换到第一页
        if(this.current === count-1 && index === 0) {
          carouselDom.style.transform = "translateX(100%)"
          carouselDom.style.transition = 'none'
          carouselDom.clientHeight   // 强制渲染
          this.moveTo(0, 'move')
        } else {
          this.moveTo(index, 'move')
        }
      },
      // 走马灯左右箭头事件
      arrowNext(type) {
        let carouselDom = document.querySelector('.carousel')
        let count = this.list.length
        // 左箭头
        if(type==1) {
          // 当前是否在第一张图,无缝切换
          if(this.current === 0) {
            carouselDom.style.transform = `translateX(-${count}00%)`
            carouselDom.style.transition = 'none'
            carouselDom.clientHeight   // 强制渲染
            this.moveTo(count-1, 'move')
          } else {
            this.moveTo(this.current-1, 'move')
          }
        }
        // 右箭头
        if(type==2) {
          // 当前是否在最后一张图,无缝切换
          if(this.current === count-1) {
            carouselDom.style.transform = "translateX(100%)"
            carouselDom.style.transition = 'none'
            carouselDom.clientHeight   // 强制渲染
            this.moveTo(0, 'move')
          } else {
            this.moveTo(this.current+1, 'move')
          }
        }
      },
      moveTo(index, type) {
        if(type=='move') {
          clearInterval(this.timer)
          this.indicator = index+1
          this.autoRun()
        }
        this.current = index
        let carouselDom = document.querySelector('.carousel')
        carouselDom.style.transform = `translateX(-${index}00%)`
        carouselDom.style.transition = '.5s'
      },
      // 跳转
      open(v) {
        if(v.link) {
          window.open(v.link)
        }
      }
    }
  }
</script>
<style scoped lang="scss">
  .box{
    width: 100%;
    height: 700px;
    margin: 0 auto;
    overflow: hidden;
    position: relative;
    .carousel{
      width: 100%;
      display: flex;
      transform: translateX(-0%);
      .item{
        width: 100%;
        position: relative;
        > img{
          width: calc(100vw - 4px);
          // height: 700px;
          display: block;
        }
      }
    }
    .indicator{
      position: absolute;
      bottom: 200px;
      left: 50%;
      transform: translateX(-50%);
      display: flex;
      justify-content: center;
      span{
        display: block;
        width: 20px;
        height: 20px;
        border: 1px solid #ddd;
        border-radius: 50%;
        margin: 0 4px;
        cursor: pointer;
        &.active{
          background-color: #fff;
          border-color: #fff;
        }
      }
    }
    .arrow_left,
    .arrow_right{
      width: 30px;
      height: 30px;
      background-color: #ccc;
      position: absolute;
      top: 50%;
      transform: translateY(-50%);
      cursor: pointer;
    }
    .arrow_left{
      left: 300px;
    }
    .arrow_right{
      right: 300px;
    }
}
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值