分类
vue

3.vue轮播图

本文取自 https://github.com/zhangxiaoshang/va-carousel 的 一个基于 vue 的图片轮播组件
我在此基础上修改了一下,自己用。

父组件代码

 <item-swiper :items=”itemSwiperOne” :interval=1000 titleText=”空间齐全” arrow=”always”></item-swiper> 

子组件代码

<template>
  <div class=”item-swiper”
    @mouseenter.stop=”handleMouseEnter”
    @mouseleave.stop=”handleMouseLeave”>
    <h1 class=”item-h1″>{{titleText}}</h1>
    <transition-group name=”list”
      tag=”div”
      class=”image-list”
      :css=”false”
      @before-enter=”beforeEnter”
      @enter=”enter”
      @before-leave=”beforeLeave”
      @leave=”leave”
      >
      <div class=”image-item”
      :style=”{width: itemWidth}” v-for=”(item, index) in list” :class=”{active: index === (total – 1) / 2}” :key=”item.id”>
        <img :src=”item.src” :alt=”item.name” class=”item-img”>
        <span class=”item-span”>{{item.title}}</span>
      </div>
    </transition-group>
    <template v-if=”arrow === ‘always’ || (hover && arrow !== ‘never’)”>
        <span key=”prev”
          class=”preview web-prev”
          @click=”prev”>
        </span>
        <span key=”next”
          class=”next web-next”
          @click=”next”>
        </span>
      </template>
  </div>

</template>

<script>
export default {
  name: ‘ItemSwiper’,
  props: {
    items: {
      type: Array,
      defalt: []
    },
    total: {
      tyep: Number,
      default:8
    },
    titleText: {
      type: String
    },
    autoplay: {
      type: Boolean,
      default: false
    },
    interval: {
      type: Number,
      default: 2000
    },
    arrow: {
      type: String,
      default: ‘hover’
    }
  },

  data() {
    return {
      list: [], // 当前显示的图片列表
      hover: false,
      timer: null,
      itemWidth: ”,
      isReverse: false
    }
  },

  beforeMount() {
    this.itemWidth = 100 / this.total + ‘%’
    this.list = this.items.slice(0, this.total)
  },

  mounted() {
    if (this.autoplay) {
      this.startTimer()
    }
  },
  methods: {
    // 下一张
    next() {
      // 如果图片列表小于需要显示的数量,则不进行滚动
      if (this.items.length < this.total) {
        return
      }

      // 向后追加一个元素,该元素为:
      //    显示列表中最后一个元素在原数组中的后一个元素
      //    如果已经是最后一个元素,则使用第一个元素

      let indexOfItems = this.items.findIndex(
        item => item.id === this.list[this.list.length – 1].id
      )

      if (indexOfItems === this.items.length – 1) {
        // 使用第一个元素
        this.list.push(this.items[0])
      } else {
        // 使用后一个元素
        this.list.push(this.items[indexOfItems + 1])
      }
      // 移除当前显示图片中的第一个
      this.list.shift()
      this.isReverse = false
    },

    // 上一张
    prev() {
      // 如果图片列表小于需要显示的数量,则不进行滚动
      if (this.items.length < this.total) {
        return
      }
      // 向前追加一个元素, 该元素为:
      //    当前展示列表中的第一个元素在原数组中的前一个元素
      //    如果已经是第一个元素,则使用最后一个元素
      let indexOfItems = this.items.findIndex(
        item => item.id === this.list[0].id
      )

      if (indexOfItems === 0) {
        this.list.unshift(this.items[this.items.length – 1])
      } else {
        this.list.unshift(this.items[indexOfItems – 1])
      }
      // 移除当前显示列表中的最后一个元素
      this.list.pop()
      this.isReverse = true
    },

    // 点击图片
    selectedItem(item, index) {
      this.$emit(‘selectedItem’, item, index)
    },

    // 开始计时器
    startTimer() {
      if (!this.interval || this.interval <= 0) {
        return
      }
      this.timer = setInterval(this.next, this.interval)
    },

    // 暂停计时器
    pauseTimer() {
      clearInterval(this.timer)
    },

    handleMouseEnter() {
      this.hover = true
      this.pauseTimer()
    },

    handleMouseLeave() {
      this.hover = false
      if (this.autoplay) {
        this.startTimer()
      }
    },

    // 列表过渡 beging
    beforeEnter(el) {
      // 只对image-item使用过渡
      let isImageItem = el.className.indexOf(‘image-item’) > -1
      if (isImageItem) {
        el.style.opacity = 0
        if (this.isReverse) {
          el.style.transform = ‘translateX(-100%)’
        } else {
          el.style.transform = ‘translateX(100%)’
        }
      }
    },

    enter(el, done) {
      // 只对image-item使用过渡
      let isImageItem = el.className.indexOf(‘image-item’) > -1
      if (isImageItem) {
        Velocity(el, { opacity: 1, translateX: ‘0px’ }, { complate: done })
//如果velocity函数不能用可以写一个定时器
setTimeout(()=>{
           el.style.transform = ‘translateX(0px)’
           el.style.opacity = ‘1’
         }, 100)
      } else {
        done()
      }
    },

    beforeLeave(el) {
      // 只对image-item使用过渡
      let isImageItem = el.className.indexOf(‘image-item’) > -1
      if (isImageItem) {
        el.style.position = ‘absolute’
        if (this.isReverse) {
          el.style.right = 0
        } else {
          el.style.left = 0
        }
      }
    },

    leave(el, done) {
      // 只对image-item使用过渡
      let isImageItem = el.className.indexOf(‘image-item’) > -1
      if (isImageItem) {
        el.style.opacity = 0
        if (this.isReverse) {
          el.style.right = `-${this.itemWidth}`
          // el.style.transform = ‘translateX(100%)’
        } else {
          el.style.transform = ‘translateX(-100%)’
        }
        setTimeout(done, 1000)
      } else {
        done()
      }
    }
    // 列表过渡 end
  }
}
</script>
<style lang=”stylus” scoped>
.item-swiper
  margin 0 auto
  height 270px
  position relative
  float left
  .item-h1
    height 28px
    font-size 28px
    color #343434
    line-height 28px
    margin 22px 0
  .image-list
    width 100%
    height 170px
    position relative
    display flex
    flex-direction row
    align-items center
    box-sizing border-box
    margin 0 auto
    overflow hidden
    .image-item
      padding 0 11.5px
      box-sizing border-box
      width 100%
      height 100%
      cursor pointer
      transition all 1s
      .item-img
        width 100%
        height 100px
        float left
      .item-span
        display inline-block
        font-size 16px
        width 128px
        height 60px
        text-align center
        line-height 60px
        background rgba(255,255,255,1)
        box-shadow 0px 2px 6px 0px rgba(1,1,1,0.3)
        border-radius 0px 0px 4px 4px
        transition all .3s
        &:hover
          box-shadow 0px 2px 6px 0px rgba(1,1,1,0.5)
  .preview, .next
    width 40px
    height 40px
    border-radius 50%
    text-align center
    position absolute
    font-size 16px
    color #409eff
    cursor pointer
    background rgba(255,255,255,1)
    transition all .3s
    box-shadow 0px 1px 4px 0px rgba(1,1,1,0.3)
    &:hover
      box-shadow 0px 1px 4px 0px rgba(1,1,1,0.5)
  .preview
    left 0px
    top 50%
    transform translateX(-100%)
  .next
    right 0px
    top 50%
    transform translateX(100%)
</style>

发表评论

电子邮件地址不会被公开。 必填项已用*标注