这是最终的效果图,可以看到无论是自动轮播,还是手动向前,向后翻,翻到头都可以做到平滑的过渡,分页器的切换也是OK的,将这个轮播组件应用于生产实践,一点问题也没有。接下来说说它的实现原理。
轮播图的html结构如下所示:slider-box区域是轮播内容区,slider-spot区域是分页区域,控制轮播图的页码切换。
上面通过用纯CSS实现轮播效果,是为了理解轮播图的原理。纯CSS实现的轮播图,在轮播项数量不确定的条件下,每一项的偏移位置不好计算。还有无法实现左右滑动切换轮播项。现在我们根据轮播图的原理,用js实现一下轮播图。
把轮播图修改成支持参数配置(配置参数参见下面),动态生成轮播项。其它的参数都比较好理解,有一个参数要说明一下。配置参数中有一项是容器id,这个参数是考虑到一个页面中可能会有多个轮播图,为了防止相互之间产生串扰。页面中引入了一个slider.js的文件,这个文件是轮播图功能的核心功能实现,接下来会重点讲解。
Slider.prototype={init(){this.createSliderDom();if(this.autoplay){this.timer=setInterval(this.toNext.bind(this,this.aniTIme),this.intervalTime);}},}createSliderDom方法内部的逻辑是在轮播外层容器my-slider下面创建轮播父容器slider-box及轮播项内容slider-item,以及分页器slider-spot及元素节点slider-item,设置轮播父容器slider-box的初始偏移。
//向后翻toNext(aniTIme){//轮播图只有一项的话,无需设置偏移if(this.imgList.length===1)return;this.playIndex++;if(this.playIndex===this.imgList.length){this.playIndex=0;}this.sliderBoxDom.style.transition=`${aniTIme/1000}sease-in-out`;this.sliderBoxDom.style.transform=`translateX(${-this.playIndex*this.moveWidth}px)`;this.setActiveSpot();},//设置当前分页按钮为高亮选中状态setActiveSpot(){this.sliderSpotDom.childNodes.forEach((item,index)=>{if(index===Math.abs(this.playIndex)){item.classList.add("active");}else{item.classList.remove("active");}});},你会发现实现的这个自动轮播功能,有个很大的问题,播放到最后一张图片重新开始下一轮播放时,过渡很不自然,有些突兀。而我们经常使用的一些轮播组件,最后一张和第一张的过渡很平滑,原因出在哪里,别人是怎么做到的?带着这个疑问,我查阅了一些资料,发现里面有点名堂。
上面的自动轮播,要想实现左移无缝轮播的效果,需要更改一下页面结构。在最后一幅图片后面,要多放置一张图片,把首张图片追加到最后一幅图的后面。
//向后翻toNext(aniTIme){if(this.imgList.length===1)return;this.playIndex++;this.sliderBoxDom.style.transition=`${aniTIme/1000}sease-in-out`;this.sliderBoxDom.style.transform=`translateX(${-this.playIndex*this.moveWidth}px)`;if(this.playIndex===this.imgList.length){this.playIndex=0;setTimeout(()=>{this.sliderBoxDom.style.transitionProperty="none";this.sliderBoxDom.style.transform=`translateX(0)`;},aniTIme);}this.setActiveSpot();},经过改造之后,现在的自动轮播效果,播放到最后一张向首张过渡时,是不是丝滑自然了很多。
如果自动轮播的方向是向右移动的话,要实现无缝轮播,需将最后一幅图放置到列表首图前面,页面结构为:
引起的代码变化:第一是在createSliderDom方法中,创建轮播元素列表时,在头部追加一张尾图。此外要将轮播容器的初始偏移位置设置为-375px,让其展示第一幅轮播图。
//向前翻toPrev(aniTIme){if(this.imgList.length===1)return;this.sliderBoxDom.style.transition=`${aniTIme/1000}sease-in-out`;this.sliderBoxDom.style.transform=`translateX(${-this.playIndex*this.moveWidth}px)`;if(this.playIndex===0){this.playIndex=this.imgList.length-1;setTimeout(()=>{this.sliderBoxDom.style.transitionProperty="none";this.sliderBoxDom.style.transform=`translateX(${-this.imgList.length*this.moveWidth}px)`;},aniTIme);}else{this.playIndex--;}this.setActiveSpot();},右移无缝轮播效果展示:可以看到第一幅图和最后一幅图的过渡效果自然流畅。