Vue2.X uses swiper custom pager to click invalid, and the next carousel page of swiper scrolls digitally in advance

Requirements:
1. 3D tilt angle carousel
2. Custom pager
3. Custom navgation left and right buttons
4. Animation uses lottfiles
5. Swiper scrolls to the current page to start digital dynamic scrolling
Development attention points
Version installation
1.npm install vue-awesome- [email protected]
2.npm install [email protected] --save
3.npm install vue-count-to
Difficulty Analysis
1. The custom pager can be clicked:
it was originally a custom pager but there was a problem (click the page No switching) I found many solutions but it didn’t work

        pagination: {
    
    
          el: ".swiper-pagination",
          clickable: true,
          type: "custom",
          //下面方法可以生成我们自定义的分页器到页面上
          renderCustom: function (swiper, current, total) {
    
    
            var paginationHtml = " ";
            for (var i = 0; i < total; i++) {
    
    
              // 判断是不是激活焦点,是的话添加active类,不是就只添加基本样式类
              if (i === current - 1) {
    
    
                paginationHtml += `<div class="swiper-pagination-customs swiper-pagination-customs-active"></div>`;
              } else {
    
    
                paginationHtml += `<div class="swiper-pagination-customs"></div>`;
              }
            }
            return paginationHtml;
          },
        },
	后来改变方案 使用原生的小圆点然后进行样式穿透
      pagination: {
    
    
          el: ".swiper-pagination",
          clickable: true,
          type: "bullets",
          //下面方法可以生成我们自定义的分页器到页面上
          // renderCustom: function (swiper, current, total) {
    
    
          //   var paginationHtml = " ";
          //   for (var i = 0; i < total; i++) {
    
    
          //     // 判断是不是激活焦点,是的话添加active类,不是就只添加基本样式类
          //     if (i === current - 1) {
    
    
          //       paginationHtml += `<div class="swiper-pagination-customs swiper-pagination-customs-active"></div>`;
          //     } else {
    
    
          //       paginationHtml += `<div class="swiper-pagination-customs"></div>`;
          //     }
          //   }
          //   return paginationHtml;
          // },
        },

2. Scroll to the current swiper page to start digital scrolling. At the
beginning, activeIndex was used and found to be inaccurate. Later, realIndex
swiper will copy the dom and the copied page will not scroll. Add this.slideToLoop(this.realIndex, 0, true) in the slideChangeTransitionEnd function ;
Add the autoplay attribute to the countTo component and jump to the current index page to change the value of endVal to reload it

 <countTo
                    :startVal="0"
                    :endVal="endValE"
                    :duration="2000"
                    autoplay
                    useEasing
                  ></countTo>

        on: {
    
    
          slideChangeTransitionEnd: function () {
    
    
            //轮播前获取当前swiper索引 activeIndex不准
            /**
             * realIndex 0  累计安装量 endValA
             * realIndex 1  累计售后服务量 endValB
             * realIndex 2  累计服务车企工单量 endValC
             * realIndex 3  电商服务工单量 endValD
             * realIndex 4 服务商平均安装时效 endValE
             * realIndex 5 评分图
             */
            // console.log(this.realIndex);
            this.slideToLoop(this.realIndex, 0, true); //防止loop:true 复制dom
            if (this.realIndex == 4) {
    
     //修复累计售后服务量滚动bug
              that.endValB = 0;
            }
            if (this.realIndex == 0) {
    
    
              //加载下一页的数据
              that.endValE = 0;
              that.endValB = that.orginB;
            }
            if (this.realIndex == 1) {
    
    
              that.endValC = that.orginC;
            }
            if (this.realIndex == 2) {
    
    
              that.endValD = that.orginD;
            }
            if (this.realIndex == 3) {
    
    
              that.endValE = that.orginE;
              that.endValA = 0;
            }
            if (this.realIndex == 4) {
    
    
              that.endValA = that.orginA;
            }
            if (this.realIndex == 5) {
    
    
              that.endValB = 0;
              that.endValC = 0;
              that.endValD = 0;
            }
          },
        },

full code

<template>
  <div class="contain">
    <div class="top">主服数据总览</div>
    <div class="middle">
      <div class="swiper">
        <div class="swiper-item">
          <swiper :options="swiperOption" ref="mySwipers" class="swipers">
            <swiper-slide class="swiper_item">
              <!-- 具体内容 -->
              <div>
                <div class="image-bg animatea">
                  <div class="imageA"></div>
                  <div class="image-bg_bg"></div>
                </div>
                <div class="title">2023年服务商安装满意度</div>
                <div class="rate">
                  <div>整体评分</div>
                  <div>
                    <el-rate
                      v-model="value1"
                      disabled
                      disabled-void-color="#10264B"
                      :colors="colors"
                    ></el-rate>
                  </div>
                </div>
                <div class="rate">
                  <div>服务态度</div>
                  <div>
                    <el-rate
                      v-model="value1"
                      disabled
                      disabled-void-color="#10264B"
                      :colors="colors"
                    ></el-rate>
                  </div>
                </div>
                <div class="rate">
                  <div>联系时效</div>
                  <div>
                    <el-rate
                      v-model="value1"
                      disabled
                      disabled-void-color="#10264B"
                      :colors="colors"
                    ></el-rate>
                  </div>
                </div>
                <div class="rate">
                  <div>安装时效</div>
                  <div>
                    <el-rate
                      v-model="value1"
                      disabled
                      disabled-void-color="#10264B"
                      :colors="colors"
                    ></el-rate>
                  </div>
                </div>
              </div>
            </swiper-slide>
            <swiper-slide class="swiper_item">
              <!-- 具体内容 -->
              <div>
                <div class="image-bg animateb">
                  <div class="imageB"></div>
                  <div class="image-bg_bgs"></div>
                </div>
                <div class="title">2023年累计安装量</div>
                <div class="num">
                  <!-- {
    
    {
    
     String(123456789).replace(/(\d)(?=(\d{3})+$)/g, "$1,") }} -->
                  <countTo
                    :startVal="0"
                    :endVal="endValA"
                    :duration="2000"
                    autoplay
                  ></countTo>
                </div>
                <div class="titles">较上年同比 <span>+123.5%</span></div>
              </div>
            </swiper-slide>
            <swiper-slide class="swiper_item">
              <!-- 具体内容 -->
              <div>
                <div class="image-bg animatec">
                  <div class="imageC"></div>
                  <div class="image-bg_bgss"></div>
                </div>
                <div class="title">2023年累计售后服务量</div>
                <div class="num">
                  <!-- {
    
    {
    
     String(a).replace(/(\d)(?=(\d{3})+$)/g, "$1,") }} -->
                  <countTo
                    :startVal="0"
                    :endVal="endValB"
                    :duration="2000"
                    autoplay
                    useEasing
                  ></countTo>
                </div>
                <div class="titles">较上年同比 <span>+123.5%</span></div>
              </div>
            </swiper-slide>
            <swiper-slide class="swiper_item">
              <!-- 具体内容 -->
              <div>
                <div class="image-bg animatea">
                  <div class="imageD"></div>
                  <div class="image-bg_bg"></div>
                </div>
                <div class="title">2023年累计服务车企工单量</div>
                <div class="num">
                  <!-- {
    
    {
    
     String(a).replace(/(\d)(?=(\d{3})+$)/g, "$1,") }} -->
                  <countTo
                    :startVal="0"
                    :endVal="endValC"
                    :duration="2000"
                    autoplay
                    useEasing
                  ></countTo>
                </div>
                <div class="titles">较上年同比 <span>+123.5%</span></div>
              </div>
            </swiper-slide>
            <swiper-slide class="swiper_item">
              <!-- 具体内容 -->
              <div>
                <div class="image-bg animatec">
                  <div class="imageE"></div>
                  <div class="image-bg_bgs"></div>
                </div>
                <div class="title">2023年电商服务工单量</div>
                <div class="num">
                  <!-- {
    
    {
    
     String(a).replace(/(\d)(?=(\d{3})+$)/g, "$1,") }} -->
                  <countTo
                    :startVal="0"
                    :endVal="endValD"
                    :duration="2000"
                    autoplay
                    useEasing
                  ></countTo>
                </div>
                <div class="titles">较上年同比 <span>+123.5%</span></div>
              </div>
            </swiper-slide>
            <swiper-slide class="swiper_item">
              <!-- 具体内容 -->
              <div>
                <div class="image-bg">
                  <div class="imageF"></div>
                  <div class="image-bg_bgss animateb"></div>
                </div>
                <div class="title">2023年服务商平均安装时效</div>
                <div class="num">
                  <!-- {
    
    {
    
     String(a).replace(/(\d)(?=(\d{3})+$)/g, "$1,") }} -->
                  <countTo
                    :startVal="0"
                    :endVal="endValE"
                    :duration="2000"
                    autoplay
                    useEasing
                  ></countTo>
                </div>
                <div class="titles">较上年同比 <span>+123.5%</span></div>
              </div>
            </swiper-slide>
          </swiper>

          <!-- 指示器 -->
          <div class="swiper-button-next"></div>
          <div class="swiper-button-prev"></div>
        </div>

        <!-- 分页 -->
        <div class="swiper-pagination"></div>
        <!-- 动画 -->
        <div id="middle" class="animatew"></div>
      </div>
    </div>
    <div class="bottom"></div>
  </div>
</template>
<script>
import lottie from "lottie-web";
import animate from "./animate.json";
import countTo from "vue-count-to";
import {
    
     Swiper, SwiperSlide } from "vue-awesome-swiper";
import "swiper/css/swiper.css";
export default {
    
    
  data() {
    
    
    let that = this;
    return {
    
    
      swiperOption: {
    
    
        speed: 3000,
        effect: "coverflow",
        slidesPerView: 3, //一下子展示3个
        slidesPerGroup: 1, //每次只转动一张图片
        coverflowEffect: {
    
    
          rotate: -30, //侧转角度(负值凸出)
          stretch: -100, //控制展示swiper之间的距离
          depth: 250, //控制两边的大小缩放
          modifier: 1,
          shadows: true,
        },
        activeIndex: 0,
        loop: true,
        navigation: {
    
    
          // 左右按钮
          nextEl: ".swiper-button-next",
          prevEl: ".swiper-button-prev",
        },
        pagination: {
    
    
          el: ".swiper-pagination",
          clickable: true,
          type: "bullets",
          //下面方法可以生成我们自定义的分页器到页面上
          // renderCustom: function (swiper, current, total) {
    
    
          //   var paginationHtml = " ";
          //   for (var i = 0; i < total; i++) {
    
    
          //     // 判断是不是激活焦点,是的话添加active类,不是就只添加基本样式类
          //     if (i === current - 1) {
    
    
          //       paginationHtml += `<div class="swiper-pagination-customs swiper-pagination-customs-active"></div>`;
          //     } else {
    
    
          //       paginationHtml += `<div class="swiper-pagination-customs"></div>`;
          //     }
          //   }
          //   return paginationHtml;
          // },
        },
        observer: true,
        cache: false,
        observeParents: true,
        lazy: {
    
    
          loadPrevNext: false,
        },
        autoplay: {
    
    
          //自动播放
          delay: 2000,
          disableOnInteraction: false, //点击了还自动轮播
          stopOnLastSlide: false,
        },
        on: {
    
    
          slideChangeTransitionEnd: function () {
    
    
            //轮播前获取当前swiper索引 activeIndex不准
            /**
             * realIndex 0  累计安装量 endValA
             * realIndex 1  累计售后服务量 endValB
             * realIndex 2  累计服务车企工单量 endValC
             * realIndex 3  电商服务工单量 endValD
             * realIndex 4 服务商平均安装时效 endValE
             * realIndex 5 评分图
             */
            // console.log(this.realIndex);
            this.slideToLoop(this.realIndex, 0, true); //防止loop:true 复制dom
            if (this.realIndex == 4) {
    
     //修复累计售后服务量滚动bug
              that.endValB = 0;
            }
            if (this.realIndex == 0) {
    
    
              //加载下一页的数据
              that.endValE = 0;
              that.endValB = that.orginB;
            }
            if (this.realIndex == 1) {
    
    
              that.endValC = that.orginC;
            }
            if (this.realIndex == 2) {
    
    
              that.endValD = that.orginD;
            }
            if (this.realIndex == 3) {
    
    
              that.endValE = that.orginE;
              that.endValA = 0;
            }
            if (this.realIndex == 4) {
    
    
              that.endValA = that.orginA;
            }
            if (this.realIndex == 5) {
    
    
              that.endValB = 0;
              that.endValC = 0;
              that.endValD = 0;
            }
          },
        },
      },
      value1: 3,
      colors: ["#146C82", "#146C82", "#146C82"],
      endValA: 0,
      endValB: 0,
      endValC: 0,
      endValD: 0,
      endValE: 0,
      orginA: 1981000,
      orginB: 1981009,
      orginC: 981000,
      orginD: 981000,
      orginE: 981000,
      timer: null,
    };
  },
  mounted() {
    
    
    this.init();
    this.getList();
    // this.timer = setInterval(()=>{
    
    
    //   this.startVal +=1;
    // },3000)
  },
  components: {
    
    
    swiper: Swiper,
    swiperSlide: SwiperSlide,
    countTo: countTo,
  },
  // 计算属性
  computed: {
    
    
    // swiper() {
    
    
    //   return this.$refs["mySwipers"].$swiper;
    // },
  },
  watch: {
    
    },
  methods: {
    
    
    /**加载lottiefiles文件 */
    init() {
    
    
      const icon = document.getElementById("middle");
      lottie.loadAnimation({
    
    
        container: icon, // 包含动画的dom元素
        renderer: "svg", // 渲染出来的是什么格式
        loop: true, // 循环播放
        autoplay: true, // 自动播放
        animationData: animate, // 动画json的路径
      });
    },
    /**查询数据 */
    getList() {
    
    
      setTimeout(() => {
    
    
        // this.endValA = this.orginA;
        // this.endValB = this.orginB;
        // this.endValC = this.orginC;
        // this.endValD = this.orginD;
        // this.endValE = this.orginE;
      }, 3000);
    },
    callBack() {
    
    
      console.log("暂停计数");
    },
  },
};
</script>
<style lang="less" scoped>
@font-face {
    
    
  font-family: "DS-Digib";
  src: url("./images/DS-Digital.ttf");
}
.num {
    
    
  //需要更改的数字添加font-family属性
  font-family: "DS-Digib";
  font-size: 74px;
  color: #49eaff;
  margin-top: 20px;
}
.contain {
    
    
  height: 100%;
  width: 100%;
  background-size: 100% 100%;
  background-attachment: fixed;
  box-sizing: border-box;
  position: relative;
  background-color: #0d1322;
  padding: 39px 22px 11px 19px;
  z-index: 100;
  .top {
    
    
    width: 100%;
    height: 67px;
    background: url("./images/top.png");
    background-size: 100% 100%;
    font-size: 44px;
    font-family: HuXiaoBo-NanShen, HuXiaoBo;
    font-weight: normal;
    color: #ffffff;
    line-height: 46px;
    box-sizing: border-box;
    letter-spacing: 7px;
    text-align: center;
  }
  .middle {
    
    
    width: 100%;
    height: calc(100% - 123px);
    box-sizing: border-box;
    background: transparent;
    .swiper {
    
    
      width: 100%;
      height: 100%;
      color: #ffffff;
      background: transparent;
      position: relative;
      .swiper-item {
    
    
        position: absolute;
        width: 80%;
        height: 394px;
        top: 12%;
        left: 50%;
        transform: translateX(-50%);
        // z-index: 100;
        .swipers {
    
    
          width: 100%;
          height: 100%;
          // border: 1px solid blue;
          .swiper_item {
    
    
            width: 400px;
            height: 394px;
            background: url("./images/swiper-bg.png");
            background-size: 100% 100%;
            display: flex;
            justify-content: center;
            align-items: center;
            > div {
    
    
              width: 450px;
              height: 360px;
              // border: 1px solid red;
              display: flex;
              flex-direction: column;
              align-items: center;
              .rate {
    
    
                display: flex;
                font-size: 14px;
                // color: rgba(20,108,129,1);
                color: #49eaff;
                margin-top: 10px;
                align-items: center;
                height: 40px;
                > div {
    
    
                  &:nth-child(1) {
    
    
                    margin-right: 10px;
                  }
                }
              }
              .image-bg {
    
    
                width: 132px;
                height: 119px;
                display: flex;
                align-items: center;
                justify-content: center;
                position: relative;
                margin-top: 20px;
              }
              .title {
    
    
                font-size: 20px;
                color: #49eaff;
                font-weight: 400;
                margin-top: 20px;
              }
              .titles {
    
    
                font-size: 18px;
                font-weight: 400;
                color: #49eaff;
                margin-top: 20px;
                // >span{
    
    
                //   font-family: "DS-Digib";
                // }
              }
              .image-bg_bg {
    
    
                width: 132px;
                height: 119px;
                background: url("./images/bga.png");
                background-size: 100% 100%;
                position: absolute;
                top: 0;
                left: 0;
                animation: move 1s infinite alternate;
              }
              .image-bg_bgs {
    
    
                width: 132px;
                height: 119px;
                background: url("./images/bga.png");
                background-size: 100% 100%;
                position: absolute;
                top: 0;
                left: 0;
                animation: move 1s infinite 0.5s alternate;
              }
              .image-bg_bgss {
    
    
                width: 132px;
                height: 119px;
                background: url("./images/bga.png");
                background-size: 100% 100%;
                position: absolute;
                top: 0;
                left: 0;
                animation: move 1s infinite 1s alternate;
              }

              .imageA {
    
    
                width: 41px;
                height: 36px;
                background: url("./images/66.png");
                background-size: 100% 100%;
              }
              .imageB {
    
    
                width: 40px;
                height: 40px;
                background: url("./images/11.png");
                background-size: 100% 100%;
              }
              .imageC {
    
    
                width: 41px;
                height: 41px;
                background: url("./images/22.png");
                background-size: 100% 100%;
              }
              .imageD {
    
    
                width: 39px;
                height: 32px;
                background: url("./images/33.png");
                background-size: 100% 100%;
              }
              .imageE {
    
    
                width: 41px;
                height: 41px;
                background: url("./images/44.png");
                background-size: 100% 100%;
              }
              .imageF {
    
    
                width: 39px;
                height: 39px;
                background: url("./images/55.png");
                background-size: 100% 100%;
              }
            }
          }
        }
      }
      .animatew {
    
    
        width: 70%;
        height: 650px;
        position: absolute;
        top: 30%;
        left: 50%;
        transform: translateX(-50%);
        // border: 1px solid #FFFFFF;
      }
    }
  }

  .swiper-button-next {
    
    
    background: url("./images/next.png");
    background-size: 100% 100%;
    --swiper-navigation-size: 90px;
    z-index: 10000 !important;
  }
  .swiper-button-prev {
    
    
    background: url("./images/pre.png");
    background-size: 100% 100%;
    --swiper-navigation-size: 90px;
    z-index: 1000000 !important;
  }
  /**自定义分页的样式 */
  .swiper-pagination {
    
    
    width: 70%;
    height: 94px;
    background: transparent;
    position: absolute;
    display: flex;
    justify-content: space-between;
    bottom: 50px;
    z-index: 1000;
    left: 50%;
    transform: translateX(-50%);
  }
  .swiper-pagination-custom {
    
    
    height: 94px;
    text-align: end !important; //这里设置分页器的位置 放在行的末尾
  }
  /*自定义分页器的样式*/
  .swiper-pagination /deep/ .swiper-pagination-bullet:nth-of-type(1) {
    
    
    width: 93px;
    height: 94px;
    display: inline-block;
    border-radius: 5px;
    margin: 0 3px;
    outline: 0;
    background: url("./images/1.png");
    background-size: 100% 100%;
    box-sizing: border-box;
    opacity: 1;
  }
  .swiper-pagination /deep/ .swiper-pagination-bullet:nth-of-type(2) {
    
    
    width: 93px;
    height: 94px;
    display: inline-block;
    border-radius: 5px;
    margin: 0 3px;
    outline: 0;
    background: url("./images/2.png");
    background-size: 100% 100%;
    box-sizing: border-box;
    opacity: 1;
  }
  .swiper-pagination /deep/ .swiper-pagination-bullet:nth-of-type(3) {
    
    
    width: 93px;
    height: 94px;
    display: inline-block;
    border-radius: 5px;
    margin: 0 3px;
    outline: 0;
    background: url("./images/3.png");
    background-size: 100% 100%;
    box-sizing: border-box;
    opacity: 1;
  }
  .swiper-pagination /deep/ .swiper-pagination-bullet:nth-of-type(4) {
    
    
    width: 93px;
    height: 94px;
    display: inline-block;
    border-radius: 5px;
    margin: 0 3px;
    outline: 0;
    background: url("./images/4.png");
    background-size: 100% 100%;
    box-sizing: border-box;
    opacity: 1;
  }
  .swiper-pagination /deep/ .swiper-pagination-bullet:nth-of-type(5) {
    
    
    width: 93px;
    height: 94px;
    display: inline-block;
    border-radius: 5px;
    margin: 0 3px;
    outline: 0;
    background: url("./images/5.png");
    background-size: 100% 100%;
    box-sizing: border-box;
    opacity: 1;
  }
  .swiper-pagination /deep/ .swiper-pagination-bullet:nth-of-type(6) {
    
    
    width: 93px;
    height: 94px;
    display: inline-block;
    border-radius: 5px;
    margin: 0 3px;
    outline: 0;
    background: url("./images/6.png");
    background-size: 100% 100%;
    box-sizing: border-box;
    opacity: 1;
  }
  // .swiper-pagination-customs:last-child {
    
    
  //   margin-right: 16px;
  // }
  /*自定义分页器激活时的样式表现*/
  .swiper-pagination /deep/ .swiper-pagination-bullet-active {
    
    
    box-shadow: 0px 0px 20px 5px rgba(62, 144, 255, 0.5);
    width: 93px;
    height: 94px;
  }

  .bottom {
    
    
    position: absolute;
    width: calc(100% - 41px);
    height: 67px;
    background: url("./images/foot.png");
    background-size: 100% 100%;
    box-sizing: border-box;
    bottom: 0;
    left: 19px;
  }
}
/deep/ .el-rate__icon {
    
    
  font-size: 22px;
}

@keyframes move {
    
    
  from {
    
    
    transform: rotate(180deg);
  }
  to {
    
    
    transform: rotate(360deg);
  }
}
</style>

display effect
insert image description here

Guess you like

Origin blog.csdn.net/weixin_44705979/article/details/129362121