总结在使用swiper插件上的一些不常见的常用的属性和遇到的问题

本文总结了使用Swiper插件时的一些不常见但实用的属性,包括网格分布、空间层次感的轮播效果。在实现过程中遇到了loop模式下事件失效的问题,提出了一种解决方案,但该方案可能导致短暂的交互闪屏。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

总结在使用swiper插件上的一些不常见的常用的属性和遇到的问题

背景

因为一直有在跟进可视化编辑项目,静态页面在设计上很多类似轮播交互,为了避免繁杂的重复工作。Swiper这个插件开源、免费、稳定、使用简单、功能强大,是架构移动终端网站的重要选择。

swiper基础使用

Swiper插件在公司项目里面用到的还是比较多的,基础使用我这里就不会过多介绍。

swiper初始化

const mySwiper=new Swiper('#mySwiper',{
    //一些swiper的基础配置
})

基于swiper几个常见的交互

1.swiper的网格分布

常见的交互是作为类似导航的头部,点击切换导航下的内容。

另外也能作为多条内容分组显示,一次只显示一组内容,一组有多个子项

如下图:

导航类型:

分组类型:

代码:

const mySwiper=new Swiper('#mySwiper',{
    centeredSlides:false,//激活页始终处于居中状态,这个属性可能会导致第一页和最后一页留白
    slidesPerView:1,//一屏显示slides的个数
    slidesPerGroup:1,//分组slides,一般和slidesPerView数据一样
    spaceBetween:10,//每一个slide之间的间距
    centerInsufficientSlides:true,//如果开启这个参数,当slides的总数小于slidesPerView时,slides居中
    breakpoints:{
        320: {
            // 当屏幕宽度大于等于320
            slidesPerView: 2,
            spaceBetween: 10,
        },
        768: {
            // 当屏幕宽度大于等于768
            slidesPerView: 4,
            spaceBetween: 10,
        },
        1280: {
            // 当屏幕宽度大于等于1280
            slidesPerView: 6,
            spaceBetween: 10,
        },
    }
})

centeredSlides留白 解决方案:可以搭配loop属性,使swiper首尾闭合,首尾就不会留白。
如果不需要loop只是想初始化的时候首尾不留白,需要搭配initialSlide属性,初始化当前激活页。

centerInsufficientSlides一般用在有自适应页面的要求,根据屏幕大小设置一屏显示slides的个数,但是又需要居中,适用大屏幕下个数较少的情况。搭配breakpoints效果很好。

breakpoints断点设定:根据屏幕宽度设置某参数为不同的值,类似于响应式布局的media only screen and (min-width: 480px)
只有部分不需要变换布局方式和逻辑结构的参数支持断点设定,如slidesPerViewslidesPerGroupspaceBetweenslidesPerColumnslidesPerGroupSkip,而像loopdirectioneffect等则无效。

2.有空间层次感的轮播(ie下切换效果比较卡顿)

插件在切换效果上有5种:默认为"slide"(位移切换),可设置为’slide’(普通切换、默认),“fade”(淡入)“cube”(方块)“coverflow”(3d流)“flip”(3d翻转)。
但是大多数需要的效果,这几个并不能满足。

const mySwiper=new Swiper('#mySwiper',{
    watchSlidesProgress:true,
    on:{
        progress(){
            const THIS = this;
            const width = THIS.slides.eq(0)[0].offsetWidth / 1.5;
            for (let i = 0; i < THIS.slides.length; i++) {
                const slide = THIS.slides.eq(i);
                const slideProgress = THIS.slides[i].progress;
                let modify = 1;
                if (Math.abs(slideProgress) > 1) {
                    modify = (Math.abs(slideProgress) - 1) * 0.08 + 1;
                }
                const translate = `${slideProgress * modify * width}px`;
                const scale = 1 - Math.abs(slideProgress) / 5;
                const zIndex = 999 - Math.abs(Math.round(10 * slideProgress));
                slide.transform(
                    `translate3d(${translate}, 0px, 0px) scale(${scale})`,
                );
                slide.css('zIndex', zIndex);
                slide.css('opacity', 1);
                if (Math.abs(slideProgress) > 3) {
                    slide.css('opacity', 0);
                }
            }
        }
    }
})

watchSlidesProgress:Progress(进度、进程)分为swiper的progress 和每个slide单独的progress。
开启这个参数来计算每个slide的progress,Swiper的progress无需设置即开启!

效果如图:

插件的目前遇到的比较难解决的问题

loop模式:会在原本slide前后复制若干个slide(默认一个)并在合适的时候切换,让Swiper看起来是循环的。react我们一般需要在slides里面触发事件的时候就是直接在元素上绑定onClick 。但是这个swiper的复制的是只一个页面,并没有复制页面内部绑定在元素上的事件,因此会造成事件失效。

如果是点击事件的话,插件在初始化的配置里面可以设置整个swiper触发到点击事件。

 const mySwiper=new Swiper('#mySwiper', {
    loop: true,   // 引发问题的根源
    on:{
        click(e){
            if(!e.target.id) return;   // e.target.id 主要起传参的作用
            console.log(e.target.id)
        }
    },
 });

为什么说这是一个目前比较难解决的问题呢?

结合可视化编辑器项目来说,编辑器里面配置的有一系列组件,包括用swiper制作的一个基础组件;

其中每一个slide都是一个容器,可以拖拽放置其他组件;

而这些组件内部绝大部分都会有自己的初始化操作甚至是绑定事件;

loop模式导致复制过后的slides里无法触发组件绑定的事件,有的甚至可能无法初始化组件,就会有空白页的情况;

而且slide内部组件的不确定性,也导致了上面那个在整个swiper上绑定方法是不可行的。

一个不太聪明的解决方法:

轮播切换会返回两个当前slide的索引,一个是activeIndex,另外一个是realIndex

正常模式下,这两个值是相等的。但是loop模式下,activeIndex会加上被loop复制出来的个数,还有被复制出来的slide会携带一个叫swiper-slide-duplicate的class类名。

可以根据这两个条件,对轮播切换的时候做一下限制,如果切换到的slide具有swiper-slide-duplicate类名,就让当前这个slide切换到当前swiper的realIndex的那个slide。

const mySwiper=new Swiper('#mySwiper',{
    loop:true,
    on:{
        slideChangeTransitionEnd:()=>{
            if (mySwiper) {
                const { realIndex, activeIndex } = mySwiper;
                const itemSlideDom = mySwiper.slides[activeIndex];
                if (itemSlideDom.className.indexOf('swiper-slide-duplicate ') > 0) {
                    mySwiper.slideToLoop(realIndex, 0, true);
                }
            }
            
        }
    }
})

不过,为什么叫一个不太聪明的解决办法呢?因为slide切换都有自己的过渡效果,这种方法会导致在交互上有一个比较短暂的闪屏,也就是复制出来的白屏会一闪而过到真实的那一屏。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值