用 vue 手寫一個h5.頁面的輪播圖


直接上代碼:

<template>
  <div
    id="hy-swiper"
    @touchstart="touchStart"
    @touchmove="touchMove"
    @touchend="touchEnd"
  >
    <div class="swiper">
      <div v-for="item in banners" class="swiper-item">
        <a :href="item.link"><img :src="item.image" alt="" /></a>
      </div>
    </div>
    <div class="swiper-circle">
      <ul>
        <li
          v-for="(item, index) in swiperItemCount"
          :class="currentIndex == item ? 'swiperItemActive' : ''"
          @click="clickItem(item)"
        ></li>
      </ul>
    </div>
  </div>
</template>

<script>
export default {
  name: "Swiper",
  props: {
    banners: {
      // 圖片內容
      type: Array,
      default() {
        return [];
      },
    },
  },
  data() {
    return {
      swiperItemCount: 0, // 輪播圖數
      swiperStyle: "", // swiper的樣式
      currentIndex: 1, // 當前的 index
      moveRatio: 0.25, // 跳轉下一張圖片所需的移動距離比例
    };
  },
  methods: {
    // 設置滾動位置
    setTransform(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`;
    },
    // 設置滾動過渡動畫
    setTransition() {
      this.swiperStyle.transition = `transform 300ms`;
    },

    // 1.先操作 dom 元素
    handleDom() {
      // 獲取 dom 對象
      let swiper = document.querySelector(".swiper");
      this.swiperItemCount = swiper.children.length;
      // 復制第一張圖片和最后一張圖片,分別放在最后面和最前面
      let nodeFirst = swiper.children[0].cloneNode(true);
      let nodeLast = swiper.children[this.swiperItemCount - 1].cloneNode(true);
      swiper.appendChild(nodeFirst); // 如果 cloneNode 報錯,那么只能在 dom 中直接添加最后一個圖片了
      swiper.insertBefore(nodeLast, swiper.children[0]);
      this.swiperStyle = swiper.style;
      this.totalWidth = swiper.offsetWidth;

      // 此時,currentIndex 的初始值為 1 ,那么先顯示第二張圖片
      this.setTransform(-this.currentIndex * this.totalWidth);
    },

    // 2. 實現用戶觸摸移動,圖片也跟隨移動,並根據滑動的方向跳轉下一張圖片的功能
    //觸摸開始
    touchStart: function (e) {
      // 停止定時器
      this.stopTimer();

      // 獲取並保存開始觸摸的位置
      this.startX = e.touches[0].pageX;
    },
    // 觸摸過程
    touchMove(e) {
      // 計算出用戶拖動的距離
      this.currentX = e.touches[0].pageX;
      this.distance = this.currentX - this.startX;
      let currentPosition = -this.currentIndex * this.totalWidth;
      let moveDistance = this.distance + currentPosition;

      // 設置當前的位置,也就是隨着觸摸移動,圖片也跟隨移動
      this.setTransform(moveDistance);
    },
    // 觸摸結束,根據滑動的方向跳轉下一張圖片
    touchEnd: function (e) {
      let distance_abs = Math.abs(this.distance);

      if (this.distance == 0) {
        return;
      } else if (
        this.distance < 0 &&
        distance_abs >= this.moveRatio * this.totalWidth
      ) {
        this.currentIndex++;
      } else if (
        this.distance > 0 &&
        distance_abs >= this.moveRatio * this.totalWidth
      ) {
        this.currentIndex--;
      }

      this.setTransition();
      this.setTransform(-this.currentIndex * this.totalWidth);
      this.currentScroll();

      this.swiperAuto();
    },

    // 3.判讀第一張和最后一張圖片的邏輯滾動,設置正確的滾動,抽取為函數
    currentScroll() {
      if (this.currentIndex == this.swiperItemCount + 1) {
        this.currentIndex = 1;
      } else if (this.currentIndex == 0) {
        this.currentIndex = this.swiperItemCount;
      }
      setTimeout(() => {
        this.swiperStyle.transition = "0ms";
        this.setTransform(-this.currentIndex * this.totalWidth);
      }, 300);
    },

    // 4. 實現點擊小圓圈跳轉相應的圖片
    clickItem(item) {
      this.stopTimer();
      this.currentIndex = item;
      this.setTransform(-this.currentIndex * this.totalWidth);

      this.swiperAuto();
    },

    // 5.設置定時器,實現輪播功能
    swiperAuto() {
      this.playTimer = setInterval(() => {
        this.currentIndex++;
        this.setTransition();
        this.setTransform(-this.currentIndex * this.totalWidth);
        this.currentScroll();
      }, 2000);
    },
    stopTimer() {
      clearInterval(this.playTimer);
    },
  },
  mounted() {
    // 由於網絡請求的圖片存在時間延遲,所以等 0.5s 讓圖片渲染出來
    setTimeout(() => {
      this.handleDom();
      this.swiperAuto();
    }, 500);
  },
};
</script>

<style lang="less">
#hy-swiper {
  position: relative;
  overflow: hidden;
  .swiper {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;

    // transform: translateX(-375px);
    div {
      float: left;
      width: 100%;
      flex-shrink: 0; //收縮因子為0 則可以使得所有圖片在同一行顯示
      img {
        width: 100%;
      }
    }
  }
  .swiper-circle {
    position: absolute;
    bottom: 10px;
    left: 50%;
    transform: translate(-50%, 0);
    ul li {
      list-style: none;
      float: left;
      width: 12px;
      height: 12px;
      border-radius: 50%;
      margin: 0 5px;
      background-color: #fff;
    }
    .swiperItemActive {
      background-color: var(--color-tint);
    }
  }
}
</style>

由於手機端是觸摸滑動的,因此與 pc 端略有不同,但是思路是一樣的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM