Swiper横向循环焦点图实现与解析

一、实现效果

请添加图片描述

二、样式与结构代码

html:

 <div class="item center">
    <div id="certify" class="col-md-12">
      <div class="swiper-container">
        <div class="swiper-wrapper">
          <div class="swiper-slide">
            <div class="com_wrap">
              <!-- 内部结构省略 -->
            </div>
          </div>
        </div>
        <div class="swiper-pagination"></div>
      </div>
    </div>
  </div>

css:

#certify {
    position: relative;
    width: 100%;
    margin: 72px auto 0;
    padding-bottom: 117px;
}

#certify .swiper-slide {
    width: 945px;
    height: 304px;
    background: #fff;
    position: relative;
    border-radius: 8px;
}

#certify .swiper-slide img {
    display: block;
    height: 150px;
    margin-bottom: 20px;
}

#certify .swiper-pagination {
    position: relative !important;
    margin-top: 30px;
    height: 10px;
}

#certify .swiper-pagination-bullets .swiper-pagination-bullet-active {
    border: 3px solid #00aadc;
    background-color: #fff;
}

#certify .swiper-button-prev {
    left: 0;
    width: 80px;
    font-size: 30px;
    text-align: center;
    line-height: 80px;
    height: 80px;
    background: inherit;
    background-color: rgba(242, 242, 242, 1);
    border: none;
}

#certify .swiper-button-next {
    right: 0;
    font-size: 30px;
    text-align: center;
    line-height: 80px;
    width: 80px;
    height: 80px;
    background: inherit;
    background-color: rgba(242, 242, 242, 1);
    border: none;
}

/* 轮播项样式 */
#certify .swiper-container .swiper-wrapper {
    display: flex;
    align-items: center;
}

三、预备知识

  1. swiper和slide都有其自身的progress(进度)值

swiper的progress不用特别设置去开启,而slide的progress则需要设置watchSlidesProgress为true来计算每个slide的进度值。
这个概念或许很抽象,但从文档中的阐述我们可以很直观地理解这个进度值究竟为何物。
对于swiper而言,活动的slide在最左边时progress为0,活动的slide在最右边时为1,其他情况平分。假如有6个slide,当活动的是第三个时swiper的progress属性是0.4,当活动的是第五个时swiper的progress属性是0.8。
而对于每个slide而言,活动块slide的progress为0,其他的依次减1。例:如果一共有6个slide,活动块slide是第三个,那么从第一个到第六个的progress属性分别是:2、1、0、-1、-2、-3。

  1. 开启 loop 选项时,Swiper 会对原始的 slide 进行复制来实现循环滚动效果
    具体来说,Swiper 会在每次滚动时在轮播列表的开头和结尾分别复制一个 slide,以创建一个无限循环的效果。
  2. 设置loopedSlides参数,它会影响 Swiper.js 在实际的循环滚动过程中生成的虚拟 slide 数据的个数
    这个参数指定了在循环滚动中每个原始 slide 周围额外生成的虚拟 slide 数量。

例如当我设置loopedSlides为2时:

(为了方便查看效果,我在监听progress变化的函数中让它遍历slide时输出了当前的slide序列号及其对应的progress值,且我实际上插入dom结构的slide数量只有三个)

在这里插入图片描述在这里插入图片描述
由图我们知道目前遍历到的slide数量变成了7个,可见它在原始的slide列表前后都复制了两个虚拟slide。

四、swiper3和swiper4-8的版本实现

// swiper3
  var mySwiper = new Swiper('.swiper-container', {
    // 开启这个参数来计算每个slide的progress(进度、进程),Swiper的progress无需设置即开启
    watchSlidesProgress: true,
    /* 
    设置slider容器能够同时显示的slides数量(carousel模式)。
    可以设置为数字(可为小数,小数不可loop),或者 'auto'则自动根据slides的宽度来设定数量。
    loop模式下如果设置为'auto'还需要设置另外一个参数loopedSlides。
    这里不要设置成你想显示的slide个数,因为他会给每个slide平分宽度
    */
    slidesPerView: 'auto',
    // 设定为true时,活动块会居中,而不是默认状态下的居左。
    centeredSlides: true,
    //在loop模式下使用slidesPerview:'auto',还需使用该参数设置所要用到的loop个数
    loopedSlides: 3,
    autoplay: 3000,
    loop: true,
    /* 
    用户操作swiper之后,是否禁止autoplay。默认为true:停止。
    如果设置为false,用户操作swiper之后自动切换不会停止,每次都会重新启动autoplay。
    操作包括触碰,拖动,点击pagination等。
    */
    autoplayDisableOnInteraction: true,
    pagination: ".swiper-pagination",
    paginationClickable: true,
    // 回调函数,当Swiper的progress被改变时执行。接受Swiper实例和progress作为参数(可选)。
    onProgress: function (swiper, progress) {
      for (i = 0; i < swiper.slides.length; i++) {
        var slide = swiper.slides.eq(i);
        // 获取当前slide的进度值
        var slideProgress = swiper.slides[i].progress;
        // 用于调整滑动时slide过渡效果的基准值
        modify = 1;
        if (Math.abs(slideProgress) > 1) {
          modify = (Math.abs(slideProgress) - 1) * 0.3 + 1;
        }
        /*这里的699设置成你实际需要的活动slide的宽度
        由此来调整其他slide的水平偏移量,
        而活动slide由于progress为0,它不会有水平偏移*/
        translate = slideProgress * modify * 699 + 'px';
        /*缩放比例根据你自己的需要调整 
        我这里设置活动slide的相邻两个slide缩放比例为成0.75*/
        scale = 1 - Math.abs(slideProgress) / 4;
        //堆叠顺序
        zIndex = 999 - Math.abs(Math.round(10 * slideProgress));
        slide.transform('translateX(' + translate + ') scale(' + scale + ')');

        slide.css('zIndex', zIndex);
        slide.css('opacity', 1);
        if (Math.abs(slideProgress) > 0.5) {
          slide.css('opacity', 0.8);
        }
        /* 根据活动的slide的progress为0,其他依次减1的特性来设置透明度/父元素overflow
            从而控制slider容器实际显示的slide个数【直接用slidesPerView会让每个slide均分容器大小
        */
        if (Math.abs(slideProgress) > 1.5) {
          slide.css('opacity', 0);
        }
      }
    },
    /*这个回调函数会在每次轮播项切换时触发,
    用于为每个轮播项设置过渡效果
    在使用 setTransition 回调函数时,Swiper 会自动计算并传递合适的过渡时间,
    以确保轮播项的切换具有平滑的过渡效果。因此可以在回调函数中直接使用传递的 transition 参数,
    也可以自己定义过渡效果*/
    onSetTransition: function (swiper, transition) {
      for (var i = 0; i < swiper.slides.length; i++) {
      	//获取当前slide
        var slide = swiper.slides.eq(i)
        /*通过jquery设置该slide的transition属性,
        这是一个css属性,用于控制过渡效果,
        这里控制的是过渡时间 体现过渡效果的延迟*/
        slide.transition(transition);
      }
    },
  })

另外,之所以要给每个轮播项slide自定义过渡效果,这是因为默认情况下,Swiper 的轮播项切换是通过 CSS 过渡属性实现的,它们没有指定过渡时间,因此切换是即时的。如果不用他计算好的transition值,那么看起来的效果就相当于slide.transition(0);

//swiper4-8
const mySwiper = new Swiper('.swiper', {
   watchSlidesProgress: true,
   slidesPerView: 'auto',
   centeredSlides: true,
   loopedSlides: 3,
   autoplay: { delay: 3000 },
   loop: true,
   autoplayDisableOnInteraction: true,
   on: {
     progress: function(swiper, progress) {
       for (let i = 0; i < swiper.slides.length; i++) {
         const slide = swiper.slides[i];
         const slideProgress = swiper.slides[i].progress;
         let modify = 1;
         if (Math.abs(slideProgress) > 1) {
           modify = (Math.abs(slideProgress) - 1) * 0.3 + 1;
         }
         const translate = slideProgress * modify * 699 + 'px';
         const scale = 1 - Math.abs(slideProgress) / 4;
         const zIndex = 999 - Math.abs(Math.round(10 * slideProgress));

         slide.style.transform = `translateX(${translate}) scale(${scale})`;
         slide.style.zIndex = zIndex;
         slide.style.opacity = 1;
         if (Math.abs(slideProgress) > 0.5) {
           slide.style.opacity = 0.8;
         }
         if (Math.abs(slideProgress) > 1.5) {
           slide.style.opacity = 0;
         }
       }
     },
     setTransition: function (transition) {
   		for (var i = 0; i < this.slides.length; i++) {
   			var slide = this.slides.eq(i)
   			slide.transition(transition);
   		}
   	}
   },
 });

本文参考了
swiper横向轮播——阶梯式滚动轮播
slide ——首尾相接の平滑切换效果
并在此基础上得出了自己的理解与总结。
如有错误,请指正。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值