轮播图的实现

avatarplhDigital nomad

前言

一个小小的轮播图,不会做。打算用vue直接js实现它。并且完成定制效果。

<template>
  <div class="swiper" :style="`height:${height}`">
    <!-- 👈按钮 -->
    <span class="turn" @click="debounceLeftMethod()">
      <svg class="icon" aria-hidden="true">
        <use xlink:href="#icon-left"></use>
      </svg>
    </span>
    <!-- 图片容器 -->
    <div class="img-container">
      <div
        v-for="(item,i) in images"
        :key="i"
        :class="`img img${i + currentIndex > 4 ? i + currentIndex - 5 : i + currentIndex}`"
      >
        <img
          :src="item"
          :alt="`轮播图${i}`"
        >
      </div>
    </div>
    <!-- 👉按钮 -->
    <span class="turn" @click="debounceRightMethod()">
      <svg class="icon" aria-hidden="true">
        <use xlink:href="#icon-right"></use>
      </svg>
    </span>

  </div>
</template>

<style lang="scss" scoped>
.swiper {
  width: 100%;
  top: 0;
  color: #fff;
  position: relative;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;

  .turn {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 30px;
    color: #ccc;
    flex: 0 0 100px;
    cursor: pointer;
    margin-top: 100px;
  }

  .img-container {
    height: 100%;
    flex: 1 1 1000px;
    display: inline-flex;
    align-items: flex-end;

    .img {
      position: absolute;
      left: calc(50% - 146px);
      transition: all 0.5s ease-in;
      &::after{
        left: 0;
        content: "";
        transition: all 0.5s ease-in;
        position: absolute;
        width: 100%;
        height: 100%;
        z-index: 1;
        background: linear-gradient(to right, #fff0, #00000029, #00000029, #fff0) no-repeat;
      }
    }
    .img0 {
      transform: scale(0.8) translateX(-200%);
      z-index: 0;
      &::after{
        background-position-x: 100px;
      }
    }
    .img1 {
      transform: scale(0.9) translateX(-100%);
      z-index: 1;
      &::after{
        background-position-x: 50px;
      }
    }
    .img2 {
      transform: scale(1);
      z-index: 2;
      &::after{
        animation: img2 0.7s ease-in 0 1 normal forwards;
        background-position-x: 5000px;
      }
    }
    .img3 {
      transform: scale(0.9) translateX(320px);
      z-index: 1;
      &::after{
        background-position-x: -50px;
      }
    }
    .img4 {
      transform: scale(0.8) translateX(700px);
      z-index: 0;
      &::after{
        background-position-x: -100px;
      }
    }
  }
}

@keyframes img2 {
  from {
    background-position-x: 10px;
  }
  to {
    background-position-x: 300px;
  }
}
</style>

<script>
import debounce from 'lodash.debounce'
const dely = ms => new Promise(resolve => setTimeout(resolve, ms))
export default {
  name: 'v-Swiper',
  data () {
    return {
      height: this.$attrs.height,
      images: this.$attrs.images,
      currentIndex: 0
    }
  },
  methods: {
    async plus () {
      if (this.currentIndex < 4) {
        this.currentIndex++
      } else {
        this.currentIndex = 0
      }
      await dely(3000)
    },
    debounceRightMethod: debounce(function() {
      if (this.currentIndex < 4) {
        this.currentIndex++
      } else {
        this.currentIndex = 0
      }
      clearInterval(window.timer)
      window.timer = setInterval(() => {
        this.plus()
      }, 3000)
    }, 500),
    debounceLeftMethod: debounce(function() {
      if (this.currentIndex > 0) {
        this.currentIndex--
      } else {
        this.currentIndex = 4
      }
      clearInterval(window.timer)
      window.timer = setInterval(() => {
        this.plus()
      }, 3000)
    }, 500),
  },
  mounted () {
    window.app = this
    window.timer = setInterval(() => {
      this.plus()
    }, 3000)
  }
}
</script>