超简单vue轮播组件

使用css3的位移及动画属性,支持无限滑动轮播及自动轮播。

代码如下:

<template>
  <div class="h-banner" :style="{height:itemHeight+'px'}">
    <ul id="bannerUl" :style="{width: itemWidth*(banner.data.length+1)+'px',height:itemHeight+'px',...boxStyle}" @touchstart="touchstart($event)" @touchmove="touchmove($event)" @touchend="touchend($event)">
      <li v-for="(item,index) in banner.data" :key="index" :style="{width:itemWidth+'px'}">
        <a :href="item.linkUrl">
          <img :src="item.picUrl" alt="">
        </a>
      </li>
      <li :key="banner.data.length" :style="{width:itemWidth+'px'}">
        <a :href="banner.data[0].linkUrl">
          <img :src="banner.data[0].picUrl" alt="">
        </a>
      </li>
    </ul>
    <div class="btn-list" :style="{top:itemHeight*0.8+'px'}">
      <a :key="index" v-for="(item,index) in banner.data" href="javascript:;" :class="{'select':index===displayIndex||(index==0&&displayIndex===banner.data.length)}" @click="displayIndex=index"></a>
    </div>
  </div>
</template>

<script>
export default {
  name: 'HBanner',
  props: {
    banner: {
      type: Object,
      default: function () {
        return {
          autoDisplayFlag: false, // 是否自动轮播
          data: [
            {
              'picUrl': 'http://gw.alicdn.com/imgextra/i2/96/O1CN01EiGkvo1Ca0Y6UsSrX_!!96-0-lubanu.jpg',
              'linkUrl': 'https://h5.m.taobao.com/'
            },
            {
              'picUrl': '//gw.alicdn.com/imgextra/i2/98/O1CN01wnOjRj1CavMBMHZlH_!!98-0-lubanu.jpg',
              'linkUrl': 'https://h5.m.taobao.com/'
            },
            {
              'picUrl': '//gw.alicdn.com/imgextra/i2/119/O1CN01KEfIYA1CkXfuwq6nv_!!119-0-lubanu.jpg',
              'linkUrl': 'https://h5.m.taobao.com/'
            },
            {
              'picUrl': '//gw.alicdn.com/imgextra/i3/18/O1CN01QcqcLg1C0HfhL9kEm_!!18-0-lubanu.jpg',
              'linkUrl': 'https://h5.m.taobao.com/'
            }
          ]
        }
      }
    }
  },
  data: function () {
    return {
      transitionDuration: '800ms', // 滑动动画时间
      autoTimer: 0, // 自动轮播定时器
      boxStyle: {
        transitionDuration: 0,
        transform: 'translate(0,0)'
      },
      itemWidth: 0, // 轮播图的宽度
      itemHeight: 0, // 轮播图的高度
      displayIndex: 0, // 当前展示的轮播图的索引
      slidePosition: 'left',
      startX: 0,
      startY: 0,
      endTime: 0,
      moveX: 0,
      moveY: 0,
      disX: 0,
      transitionendCallback: function () {
        console.log('ok')
      }
    }
  },
  watch: {
    displayIndex: function () {
      setTimeout(() => {
        if (this.displayIndex >= 0) {
          this.boxStyle = {
            transitionDuration: this.transitionDuration,
            transform: 'translate(' + (-this.displayIndex * this.itemWidth) + 'px,0)'
          }
          this.transitionendCallback = function () {
            this.boxStyle.transitionDuration = '0s'
            if (this.displayIndex >= this.banner.data.length) {
              this.boxStyle.transitionDuration = '0s'
              this.boxStyle.transform = 'translate(0,0)'
              this.displayIndex = 0
            }
            if (this.autoDisplayFlag) {
              this.autoDisplay()
            }
          }
        } else {
          this.displayIndex = 0
        }
      }, 0)
    }
  },
  created: function () {
    let that = this
    this.$nextTick(() => {
      if (this.banner.autoDisplayFlag) {
        this.autoDisplay()
      }
      this.computeWidthHeight()
      this.boxStyle = {
        transitionDuration: '0',
        transform: 'translate(' + (-this.displayIndex * this.itemWidth) + 'px,0)'
      }
      document.getElementById('bannerUl').addEventListener('transitionend', function () {
        that.transitionendCallback()
      }, false)
      window.onresize = function () {
        that.computeWidthHeight()
      }
    })
  },
  computed: {},
  mounted: function () {
  },
  methods: {
    computeWidthHeight() {
      let that = this
      this.itemWidth = window.innerWidth
      var myImg = new Image()
      myImg.src = this.banner.data[0].picUrl
      myImg.onload = function () {
        that.itemHeight = myImg.height / myImg.width * that.itemWidth
      }
    },
    /**
     * 自动轮播
     */
    autoDisplay: function () {
      if (this.banner.autoTimer) {
        clearInterval(this.autoTimer)
      }
      this.autoTimer = setInterval(() => {
        this.displayIndex++
      }, 2000)
    },
    touchstart(e) {
      clearInterval(this.autoTimer)
      e = e || event
      this.startTime = new Date().getTime()
      if (e.touches.length === 1) {
        this.startX = e.touches[0].clientX // 记录开始位置
        this.startY = e.touches[0].clientY // 记录开始位置
      }
    },
    touchmove(e) {
      e = e || event
      if (e.touches.length === 1) {
        // 滑动时距离浏览器左侧的距离
        this.moveX = e.touches[0].clientX
        this.disX = this.startX - this.moveX
        if (this.disX < 0) { // 右滑
          this.slidePosition = 'right'
          if (this.displayIndex <= 0) { // 在最左边不许往右滑动
          } else {
            this.boxStyle = {
              transitionDuration: '0',
              transform: 'translate(' + (-this.displayIndex * this.itemWidth - this.disX) + 'px,0)'
            }
          }
        } else { // 左滑
          this.slidePosition = 'left'
          if (this.displayIndex >= this.banner.data.length) { // 在最右边不许往左滑动
          } else {
            this.boxStyle = {
              transitionDuration: '0',
              transform: 'translate(' + (-this.displayIndex * this.itemWidth - this.disX) + 'px,0)'
            }
          }
        }
      }
    },
    touchend(e) {
      e = e || event
      this.endTime = new Date().getTime()
      if (Math.abs(this.moveX - this.startX) > this.itemWidth / 3) {
        if (this.slidePosition === 'left') {
          this.displayIndex++
        } else {
          this.displayIndex--
        }
      } else {
        this.boxStyle = {
          transitionDuration: '200',
          transform: 'translate(' + (-this.displayIndex * this.itemWidth) + 'px,0)'
        }
        this.transitionendCallback = function () {
          this.boxStyle.transitionDuration = '0s'
        }
      }
    }}
}
</script>

<style scoped lang="less">
  .h-banner {
    * {
      margin: 0;
      padding: 0;
    }
    position: relative;
    margin: 0;
    padding: 0;
    min-height: 100%;
    overflow: hidden;
    ul {
      position: absolute;
      left: 0;
      overflow: hidden;
      &:after {
        content: "";
        clear: both;
      }
      li {
        float: left;
        list-style: none;
        a {
          display: block;
          img {
            width: 100%;
          }
        }
      }
    }
    .btn-list {
      position: absolute;
      top: 41%;
      right: 1rem;
      a {
        display: inline-block;
        margin-right: 0.5rem;
        width: 0.5rem;
        height: 0.5rem;
        border-radius: 0.5rem;
        border: 1px solid #fff;
        background: rgba(0,0,0,.3);
        box-sizing: border-box;
        &.select {
          background: #fff;
        }
      }
    }
  }
</style>

 

posted @ 2019-07-10 13:32  大仙儿呀  阅读(6888)  评论(0编辑  收藏  举报