Vue(三十一)轮播组件

直接上源码

(1)组件文件 Carousel.vue

<template>
  <div class="carousel-component">
    <div ref="carouselItems" class="carousel-items" :style="carouselStyle" @mouseenter="handleStop" @mouseleave="handlePlay">
      <div class="carousel-items-images">
        <img :src="dataImage[dataImage.length-1].src" alt="" srcset="">
      </div>
      <div class="carousel-items-images" v-for="(item, index) in dataImage" :key="index">
        <img :src="item.src" alt="" srcset="">
      </div>
      <div class="carousel-items-images">
        <img :src="dataImage[0].src" alt="" srcset="">
      </div>
    </div>
    <div class="carousel-btn">
      <div @click="handleJump(index+1)" v-for="(item, index) in dataImage" :key="index" :class="currentIndex == index+1?'carousel-btn-items active':'carousel-btn-items'"></div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'my-carousel',
  props: {
    dataImage: {
      type: Array,
      default: function () {
        return []
      }
    },
    initialImgWidth: {
      type: Number,
      default: 990
    },
    initialDistance: {
      type: Number,
      default: -990
    },
    initialSpeed: {
      type: Number,
      default: 40
    },
    initialInterval: {
      type: Number,
      default: 3
    }
  },
  data () {
    return {
      imgWidth: this.initialImgWidth,
      distance: this.initialDistance,
      currentIndex: 1,
      transitionEnd: true,
      speed: this.initialSpeed
    }
  },
  computed: {
    carouselStyle () {
      return {
        transform: `translate3d(${this.distance}px, 0, 0)`
      }
    },
    interval () {
      return this.initialInterval * 1000
    }
  },
  methods: {
    init () {
      this.handlePlay()
      window.onblur = function () { this.handleStop() }.bind(this)
      window.onfocus = function () { this.handlePlay() }.bind(this)
    },
    move (offset, direction, speed) { // 移动方法
      if (!this.transitionEnd) return
      this.transitionEnd = false
      direction === -1 ? this.currentIndex += offset / this.imgWidth : this.currentIndex -= offset / this.imgWidth
      if (this.currentIndex > this.dataImage.length) this.currentIndex = 1
      if (this.currentIndex < 1) this.currentIndex = this.dataImage.length
      const destination = this.distance + offset * direction
      this.animate(destination, direction, speed)
    },
    animate (des, direc, speed) {
      if (this.temp) {
        window.clearInterval(this.temp)
        this.temp = null
      }
      this.temp = window.setInterval(() => {
        if ((direc === -1 && des < this.distance) || (direc === 1 && des > this.distance)) {
          this.distance += speed * direc
        } else {
          this.transitionEnd = true
          window.clearInterval(this.temp)
          this.distance = des
          if (des < -this.imgWidth*this.currentIndex) this.distance = -this.imgWidth
          if (des > -this.imgWidth) this.distance = -this.imgWidth*this.currentIndex
        }
      }, 20)
    },
    handleJump (index) { // 小圆点点击跳转
      const direction = index - this.currentIndex >= 0 ? -1 : 1
      const offset = Math.abs(index - this.currentIndex) * this.imgWidth
      const jumpSpeed = Math.abs(index - this.currentIndex) === 0 ? this.speed : Math.abs(index - this.currentIndex) * this.speed
      this.move(offset, direction, jumpSpeed)
    },
    handlePlay () { // 启动自动轮播定时器
      if (this.timer) {
        window.clearInterval(this.timer)
        this.timer = null
      }
      this.timer = window.setInterval(() => {
        this.move(this.imgWidth, -1, this.speed)
      }, this.interval)
    },
    handleStop () { // 关闭定时器
      window.clearInterval(this.timer)
      this.timer = null
    }
  },
  mounted () {
    this.init()
  }
}
</script>

<style lang="scss" scoped>
.carousel-component{
  height: 500px;
  position: relative;
  overflow: hidden;
  .carousel-items{
    display: flex;
    position: absolute;
    width: 100%;
    height: 100%;
    .carousel-items-images{
      width: 100%;
      height: 100%;
      img{
        height: 100%;
        user-select: none;
      }
    }
  }
  .carousel-btn{
    height: 30px;
    position: absolute;
    bottom: 20px;
    left: 0;
    right: 0;
    margin: auto;
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    .carousel-btn-items{
      width: 8px;
      height: 8px;
      border-radius: 8px;
      background-color: #fff;
      border:1px solid #fd3555;
      margin:0 3px;
      cursor: pointer;
      &.active{
        width: 16px;
        background-color: #fd3555;
      }
    }
  }
}
</style>

 

2.父组件中引入

<template>
  <div class="home-page">
    <div class="home-nav">
      <div class="container">
        <div class="left-nav"></div>
        <div class="banner" ref="banner">
          <my-carousel :dataImage="dataImage"></my-carousel>
        </div>
      </div>
    </div>
</template>

<script>
import Carousel from '../components/carousel/Carousel'
export default {
  name: 'my-home',
  data () {
    return {
      dataImage: [{
        src: 'xxxxxx/banner1.jpg'
      }, {
        src: 'xxxxxx/banner2.jpg'
      }, {
        src: 'xxxxxx/banner3.jpg'
      }]
    }
  },
  components: {
    'my-carousel': Carousel
  }
}
</script>

 

3.效果

 

posted @ 2018-10-16 14:09  yulingjia  阅读(253)  评论(0编辑  收藏  举报