一、实现效果
二、样式与结构代码
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;
}
三、预备知识
- 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。
- 开启 loop 选项时,Swiper 会对原始的 slide 进行复制来实现循环滚动效果
具体来说,Swiper 会在每次滚动时在轮播列表的开头和结尾分别复制一个 slide,以创建一个无限循环的效果。 - 设置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 ——首尾相接の平滑切换效果,
并在此基础上得出了自己的理解与总结。
如有错误,请指正。