vue uses swiper rotation chart

The realization and principle explanation of simple carousel chart

swiper.vue
<template>
    <div id="hy-swiper">
      <div class="swiper" @touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd">
        <slot></slot>
      </div>
      <slot name="indicator">
      </slot>
      <div class="indicator">
        <slot name="indicator" v-if="showIndicator && slideCount>1">
          <div v-for="(item, index) in slideCount" class="indi-item" :class="{active: index === currentIndex-1}" :key="index"></div>
        </slot>
      </div>
    </div>
</template>

<script>
	export default {
		name: "Swiper",
    props: {
      interval: { type: Number, default: 3000 },
      animDuration: {  type: Number, default: 300 },
      moveRatio: { type: Number,  default: 0.25 },
      showIndicator: {  type: Boolean, default: true }
    },
    data: function () {
		  return {
        slideCount: 0, // Element number
        totalWidth: 0, // Width of swiper
        swiperStyle: {}, // swiper style
        currentIndex: 1, // Current index
        scrolling: false, // Scrolling or not
      }
    },
    mounted: function () {
      // 1. Operate DOM and add Slide before and after
      setTimeout(() => {
        this.handleDom();   
        this.startTimer();	 // 2. Turn on timer
      }, 100)
    },
    methods: {
		  /** * Timer operation  */
      startTimer: function () {
		    this.playTimer = window.setInterval(() => {
		      this.currentIndex++;
		      this.scrollContent(-this.currentIndex * this.totalWidth);
        }, this.interval)
      },
      stopTimer: function () {  window.clearInterval(this.playTimer);  },

      /**  * Scroll to the correct position  */
      scrollContent: function (currentPosition) {
        // 0. Setting scrolling
        this.scrolling = true;
        // 1. Start rolling animation
        this.swiperStyle.transition ='transform '+ this.animDuration + 'ms';
        this.setTransform(currentPosition);
        // 2. Judge the rolling position
        this.checkPosition();
        // 4. Rolling complete
        this.scrolling = false
      },

      /**  * Verify correct position  */
      checkPosition: function () {
        window.setTimeout(() => {
          // 1. Check the correct position
          this.swiperStyle.transition = '0ms';
          if (this.currentIndex >= this.slideCount + 1) {
            this.currentIndex = 1;
            this.setTransform(-this.currentIndex * this.totalWidth);
          } else if (this.currentIndex <= 0) {
            this.currentIndex = this.slideCount;
            this.setTransform(-this.currentIndex * this.totalWidth);
          }
          // 2. End the callback after the move
          this.$emit('transitionEnd', this.currentIndex-1);
        }, this.animDuration)
      },

      /** * Set scroll position  */
      setTransform: function (position) {
        this.swiperStyle.transform = `translate3d(${position}px, 0, 0)`;
        this.swiperStyle['-webkit-transform'] = `translate3d(${position}px), 0, 0`;
        this.swiperStyle['-ms-transform'] = `translate3d(${position}px), 0, 0`;
      },

      /*** Operate Dom and add Slide before and after DOM */
		  handleDom: function () {
        // 1. Get the element to operate
        let swiperEl = document.querySelector('.swiper');
        let slidesEls = swiperEl.getElementsByClassName('slide');
        // 2. Number of saved
        this.slideCount = slidesEls.length;
        // 3. If it is larger than 1, add a slide before and after
        if (this.slideCount > 1) {
          let cloneFirst = slidesEls[0].cloneNode(true);
          let cloneLast = slidesEls[this.slideCount - 1].cloneNode(true);
          swiperEl.insertBefore(cloneLast, slidesEls[0]);
          swiperEl.appendChild(cloneFirst);
          this.totalWidth = swiperEl.offsetWidth;
          this.swiperStyle = swiperEl.style;
        }
        // 4. Let the swiper element display the first one (currently the last one added before)
        this.setTransform(-this.totalWidth);
      },

      /**   * Handling of drag events  */
      touchStart: function (e) {
        // 1. If you are scrolling, you cannot drag
        if (this.scrolling) return;
        // 2. Stop timer
        this.stopTimer();
        // 3. Save where to start scrolling
        this.startX = e.touches[0].pageX;
      },

      touchMove: function (e) {
        // 1. Calculate the distance dragged by the user
        this.currentX = e.touches[0].pageX;
        this.distance = this.currentX - this.startX;
        let currentPosition = -this.currentIndex * this.totalWidth;
        let moveDistance = this.distance + currentPosition;
        // 2. Set the current position
        this.setTransform(moveDistance);
      },

      touchEnd: function (e) {
        // 1. Get the moving distance
        let currentMove = Math.abs(this.distance);
        // 2. Judge the final distance
        if (this.distance === 0) {  return } 
        else if (this.distance > 0 && currentMove > this.totalWidth * this.moveRatio) { // Move right more than 0.5
          this.currentIndex--
        } 
        else if (this.distance < 0 && currentMove > this.totalWidth * this.moveRatio) { // Move left more than 0.5
          this.currentIndex++
        }
        // 3. Move to the correct position
        this.scrollContent(-this.currentIndex * this.totalWidth);
        // 4. Restart the timer after the movement
        this.startTimer();
      },

      /** * Control previous, next */
      previous: function () {  this.changeItem(-1);  },
      next: function () {   this.changeItem(1);  },

      changeItem: function (num) {
        // 1. Remove timer
        this.stopTimer();
        // 2. Modify index and location
        this.currentIndex += num;
        this.scrollContent(-this.currentIndex * this.totalWidth);
        // 3. Add timer
        this.startTimer();
      }
    }
	}
</script>

<style scoped>
  #hy-swiper { overflow: hidden;  position: relative; }
  .swiper {	display: flex; }
  .indicator {
    display: flex;
    justify-content: center;
    position: absolute;
    width: 100%;
    bottom: 8px;
  }
  .indi-item {
    box-sizing: border-box;
    width: 8px;
    height: 8px;
    border-radius: 4px;
    background-color: #fff;
    line-height: 8px;
    text-align: center;
    font-size: 12px;
    margin: 0 5px;
  }
  .indi-item.active {  background-color: rgba(212,62,46,1.0); } //Click the dot to switch the picture
</style>
SwiperItem.vue
<template>
  <div class="slide"> <slot></slot> </div>
</template>
<script>  export default {  name: "Slide" }	</script>
<style scoped>
  .slide {  width: 100%; flex-shrink: 0;  }
  .slide img {  width: 100%; }
</style>

The default value of flex shrink is 1. When the width of the parent element is less than the sum of the width of all the child elements, the width of the child elements decreases. The higher the value, the more severe the decrease. A value of 0 means no reduction.

index.js

import Swiper from './Swiper'
import SwiperItem from './SwiperItem'
export { Swiper, SwiperItem}
HomeSwiper.vue uses Swiper, SwiperItem subcomponent
<template>
  <swiper>
    <swiper-item v-for="item in banners">
      <a :href="item.link">  <img :src="item.image" alt=""> </a>
    </swiper-item>
  </swiper>
</template>

<script>
  import {Swiper, SwiperItem} from 'components/common/swiper'
  export default {
    name: "HomeSwiper",
    props: { banners: {  type: Array, default() { return [] } } },
    components: {  Swiper,  SwiperItem }
  }
</script>
home.vue uses the HomeSwiper component
<template>
  <div id="home">  <home-swiper :banners="banners"/> </div>
</template>

<script> 
  import HomeSwiper from './childComps/HomeSwiper'
  import {getHomeMultidata} from "network/home";
  export default {
    name: "Home",
    components: {  HomeSwiper, },
    data() { return { banners: []  } },
    created() {
      // 1. Request multiple data
      getHomeMultidata().then(res => {
        this.banners = res.data.banner.list;   
      })
    }
  }
</script>
Published 94 original articles, won praise 22, visited 40000+
Private letter follow

Tags: Vue less network

Posted on Wed, 05 Feb 2020 09:46:16 -0500 by roxiroxi