废话不多说先上效果
使用例子1
//例子
new Carousel({
el:'#carousel',
images: ['./images/1.jpg','./images/2.jpg','./images/3.jpg','./images/4.jpg','./images/5.jpg','./images/6.jpg','./images/1.png','./images/2.png'],
pre:'#pre',
next: '#next',
num: 5,//同屏显示五张
autoplay: true,
delayed: 3000
})
效果
当然调整num属性的值可以相应同屏显示 不同图片数量
属性功能介绍
/*
* 参数选项
* el 必填,css选择器,轮播图dom
* images 必填,提供轮播的图片的数组
* pre 选填,css选择器,上一张按钮
* next 选填,css选择器,下一张按钮
* num 选填,默认5,同屏显示图片的数量,数值应该比 images图片数量小
* autoplay 选填,默认false 是否自动轮播
* delayed 选填,默认 3000, 自动轮播的时间间隔毫秒
* */
html结构
<div id="carousel" class="carousel">
<ul class="slider-content" >
</ul>
</div>
<!--按钮不是必须的,可自定义-->
<div class="btns" style="width: 100px; margin: 0 auto;">
<button id="pre">上一张</button>
<button id="next">下一张</button>
</div>
css
*{
padding: 0;
margin: 0;
}
ul,li{
list-style: none;
}
.carousel{
width: 1200px;
height: 120px;
position: relative;
border: 2px solid #ccc;
z-index: 100;
padding: 0 !important;
margin: 0 auto;
overflow: hidden;
}
.carousel .slider-content{
position: absolute;
left: 0;
top: 0;
height: 100%;
font-size: 0;
white-space: nowrap;
}
.carousel .slider-content .item{
width: 240px;
height: 100%;
display: inline-block;
font-size: 16px;
color: #383838;
text-align: center;
}
.carousel .slider-content .item img{
width: 100%;
height: 100%;
object-fit: fill;
}
.carousel .slider-content .item a{
display: block;
width: 100%;
height: 100%;
overflow: hidden;
box-sizing: border-box;
padding-right: 1px;
padding-left: 1px;
color: #333;
text-decoration: none;
}
.ease2{
transition: ease .6s;
}
核心JQ代码
function Carousel(options){
var defaultOpt = {
el: '',//轮播图class、id 等jq选择器
images: [],//轮播图图片数组
pre: '',//上一图按钮
next: '',//下一图按钮
num: 5,//一屏显示图片数量
autoplay: false,//自动轮播
delayed: 3000
}
var opt = Object.assign({}, defaultOpt, options);//合并用户参与与默认参数
var isrunTime = false,//防抖
autoRunTirmer = 0,
carDom = $(opt.el);
if(carDom.length == 0) return;
var slider = carDom.find('.slider-content');
var carDomWidth = carDom.width();//轮播图整体宽度
var sliderWidth = carDomWidth/opt.num; //每一个图宽度
var num = opt.num;
var imgList = opt.images;
var newImgList = imgList;
function init(){
if( imgList.length > num){//无缝核心1
newImgList = imgList.slice(imgList.length - num,imgList.length).concat(imgList).concat(imgList.slice(0,num));
}
var str;
for(var i = 0; i < newImgList.length; i++){//循环生成轮播图dom
str += '<li class="item" style="width: ' + sliderWidth +'px;"><a href="#"><img src="'+ newImgList[i] +'"/></a></li>'
}
slider.append(str);
var sliderLeft = 0;
if(num < imgList.length){
sliderLeft = -carDomWidth;
}
slider.css('left', sliderLeft + 'px');
}
init();
var count = 1;
function run(pre){
if(isrunTime || num >= imgList.length){
return '';
}
isrunTime = true;
clearTimeout(autoRunTirmer);
slider.addClass('ease2')
var left = slider.position().left;
var newLeft;
if(pre){
newLeft = left + sliderWidth;
count --;
}else{
newLeft = left - sliderWidth;
count ++;
}
if(count > imgList.length){//下一张最后一张处理(无缝核心2)
count = 1;
setTimeout(function(){
slider.removeClass('ease2')
slider.css('left', -carDomWidth + 'px');
},1000)
}
if(count <= -num + 1){ //上一张第一张处理(无缝核心2)
count = imgList.length - num + 1;
let relLeft = -imgList.length * sliderWidth;
setTimeout(function(){
slider.removeClass('ease2')
slider.css('left', relLeft + 'px');
},1000)
}
slider.css('left',newLeft + 'px');
setTimeout(function(){
isrunTime = false;
},1000);
setTimeout(function(){
isrunTime = false;
},1000);
autoPlay();
}
function autoPlay(){
if(opt.autoplay){
autoRunTirmer = setTimeout(function(){
run();
},opt.delayed);
}
}
autoPlay();
$(opt.next).click(function(){
run();
})
$(opt.pre).click(function(){
run('pre');
})
carDom.on('mouseenter',function(){
clearTimeout(autoRunTirmer);
});
carDom.on('mouseleave',function(){
autoPlay();
});
}
原理讲解
1.其实感觉轮播图没什么原理可讲的,哈哈。
难点主要是无缝,
比如此时图片总数是5张,要同屏显示三张
那么第一张切上一张时,此刻是没有的。要做到无缝。必须复制后面第五张到整个图片列表的前面。
这样1切上一张,视觉上是 5 。当第一张是5时再切上一张呢?是4,再上一张是3... ...
同理 5切下一张 是1。
整个轮播图最终形态如下
无缝的效果时,当切上一张到 3 的位置是,瞬间暂时去掉过度效果并且将整个列表的位置调整,
在视觉上看来只是4切换到3,在代码层面这个时候图片列表已经换位置啦,此时再点上一张,当然是2、1、5... ...。
同理切下一张也一样,当切到最后一张时,瞬间切换整个列表的位置
同时配合防抖处理,最终就可得到一个无缝切换的轮播图了。