前言:轮播图是前端很普通很常见的一种网页动效,很多框架或插件都封装了轮播图组件供我们使用,例如Bootstrap,layui,swiper等框架都有轮播图组件,并且也是比较好用的。但往往我们需要做的轮播图并非完全中规中矩的,或许有些另类,此时框架可能就无法满足我们另类的需求了,需要自己写轮播。一直以来也很少自己写,我个人喜欢使用swiper插件,但本次遇到了一个比较另类的轮播,因此自己写了一个无缝轮播,将轮播图设计思路逻辑简单记录于此。
首先是基础网页布局,布局方面不多讲,很基础,主要分3块:轮播图块,指示器块,左右切换按钮块。直接上代码:
<div id="bgblock">
<ul class="carousel">
<li class="carousel_item">
<img src="image/1.jpg" />
</li>
<li class="carousel_item">
<img src="image/2.jpg" />
</li>
<li class="carousel_item">
<img src="image/3.jpg" />
</li>
<li class="carousel_item">
<img src="image/4.jpg" />
</li>
<li class="carousel_item">
<img src="image/5.jpg" />
</li>
</ul>
<ul class="pointer">
<li class="pointer_item pointer_item_active">1</li>
<li class="pointer_item">2</li>
<li class="pointer_item">3</li>
<li class="pointer_item">4</li>
<li class="pointer_item">5</li>
</ul>
<div class="carousel_btn carousel_btn_left"></div>
<div class="carousel_btn carousel_btn_right"></div>
</div>
其次是css,整体来讲也十分基础,其中有三点需要注意:轮播图父容器需要设置定位属性,因为轮播滚动主要依赖于定位后的left属性来控制。具体轮播图li需进行浮动,轮播图父容器需设置overflow:hidden属性,用来隐藏超出的其他轮播图。
*{
padding: 0;
margin: 0;
}
#bgblock{
width: 960PX;
height: 400px;
margin: 0 auto;
position: relative;
overflow: hidden;
}
.carousel{
width: 960px;
height: 400px;
position: absolute;
left: 0;
top: 0;
overflow: hidden;
}
.carousel_item{
float: left;
width: 960px;
height: 400px;
list-style-type: none;
}
.carousel_item>img{
width: 960px;
height: 400px;
}
.pointer{
width: 225px;
height: 50px;
border-radius: 25px;
position: absolute;
bottom: 10px;
left: 50%;
margin-left: -150px;
}
.pointer_item{
width: 30px;
height: 30px;
list-style-type: none;
float: left;
margin-top: 10px;
margin-left: 15px;
text-align: center;
line-height: 30px;
cursor: pointer;
border-radius: 15px;
background-color:#ffffff;
}
.pointer_item_active{
color: #FFFFFF;
background: #31c27c;
}
.carousel_btn{
width: 50px;
height: 48px;
cursor: pointer;
position: absolute;
top: 50%;
margin-top: -24px;
background-repeat: no-repeat;
}
.carousel_btn_left{
left: 0;
background-image: url(../image/聚合维度左按钮.png);
}
.carousel_btn_right{
right: 0;
background-image: url(../image/聚合维度右按钮.png);
}
重点来了,js轮播逻辑:在此使用了JQuery库简化dom操作,无论是js或是jq功能逻辑都一样,区别只是具体dom操作或方法的写法而已。如何实现轮播?
首先需要思考轮播图都有哪些功能?1:点击左右切换按钮,向上或向下翻页。2:指示器指示当前轮播位置,其次点击指示器可直接轮播至该轮播页。3:自动进行轮播。将功能细化后要做什么就十分清楚了。第一步当然是获取可能用到的dom元素,将其绑定在一个变量上方便我们后面操作。其次我们需要定义两个非常重要的变量:autoplay(是否自动播放),nowIndex(指示器位置,或者说轮播位置)。
var carousel=$(".carousel"),//轮播图
carouselItem=$(".carousel_item"),//轮播图item
carouselItemWidth=carouselItem.eq(0).width(),//一个img的宽度
pointer_item=$(".pointer_item"),//指示器
btnLeft=$(".carousel_btn_left"),//左按钮
btnRight=$(".carousel_btn_right");//右按钮
var nowIndex=0,
autoplay=true;
第二步,实现点击左右切换按钮,轮播图轮播至下一张功能。如何实现?左侧按钮点击后,会切换至上一张图,因此nowindex应该--。右侧按钮点击后,会切换至下一张图因此nowindex应该++。如何让其切换,上面在css部分已经说过了,主要是通过定位后的left属性来进行控制。第一张img的left就应该为0,第二张为-1个li的宽度,第3张为-2个li的宽度...最后1张为-要轮播的图的张数-1。若通过直接改变left值会发现并没有滚动效果而至直接切换,若想要img滚动切换效果额采用jq的动画animate()方法实现。完成上述步骤后运行会发现一个问题第一张时点击左侧按钮和最后一张点击右侧按钮时nowindex为-1或6,轮播位置空白。此时就需要进行条件判断,限定nowindex保证其正常。具体为:当nowindex<0时,让其等于轮播img数量-1,nowindex>轮播数量-1
时让其等于0。
第三步:自动播放,想要自动播放其实只需添加一个定时器:setInterval,设定间隔时间,每隔多少秒执行一次。仔细想想自动播放其实就是自己不断地播放下一张,也就是执行右侧(下一张)按钮的click事件。自动播放后测试时又发现一个小问题:刚刚点击左右按钮后,切换了一张,然后定时器时间到了又自动切换了一次,这样使得用户体验很差。因此我们需要利用autoplay变量帮助我们关闭开启自动播放。当用户鼠标悬停在左右按钮上时,代表用户想要手动切换,因此我们应该设置关闭自动轮播,当用户鼠标离开这两按钮开启轮播。实现开启关闭轮播可以通过开启关闭定时器来实现,但相对麻烦在此选择利用autoplay变量,在定时器中判断变量值,为true则执行轮播代码,否则不执行即可。
第四步:做到此其实已经实现了整个轮播,可以正常轮播了,但是会有一个小缺陷:即在第一张向上,最后一张向下时切换会有“缝隙”,具体不是很好描述,做完上面的步骤测试就会明白。如何让其无缝滚动呢?无缝滚动的思路就是:将第一个img复制一份添加至父元素最后,当其为第一张向上时直接切换至至复制的这张(也就是现在的第6张),然后再滚动至上一张(第5张,以前的最后一张),最后一张向下:切换至第6张(复制的那张)再滚动至第一张,这样肉眼其实看不到切换这个步骤,因此就是无缝轮播。整个代码如下:
carousel.append(carouselItem.eq(0).clone());
carouselItem=$(".carousel_item");
carousel.width(carouselItem.length*960);
//左切换按钮事件
btnLeft.click(function(){
nowIndex--;
imgTransfrom(nowIndex);
})
//右切换按钮事件
btnRight.click(function(){
nowIndex++;
imgTransfrom(nowIndex);
})
//指示器切换事件
pointer_item.click(function(){
var index=$(this).index();
imgTransfrom(index);
})
//鼠标悬停自动播放停止事件
$(".carousel_btn_left,.carousel_btn_right").hover(function(){
autoplay=false;
},function(){
autoplay=true;
})
//自动播放
setInterval(function(){
if(autoplay){
btnRight.click();
}
},3000)
function imgTransfrom(index){
if(index<0){
index=carouselItem.length-2;
carousel.css("left",-(carouselItem.length-1)*carouselItemWidth);
}
if(index>carouselItem.length-1){
index=1;
carousel.css("left",0);
}
nowIndex=index;
console.log("index:"+nowIndex);
carousel.animate({
left:-index*carouselItemWidth
},500)
if(index==carouselItem.length-1){
pointer_item.eq(0).addClass("pointer_item_active");
pointer_item.eq(0).siblings().removeClass("pointer_item_active");
}else{
pointer_item.eq(index).addClass("pointer_item_active");
pointer_item.eq(index).siblings().removeClass("pointer_item_active");
}
}
至此,简单的无缝轮播就彻底完成了!在此举例写的这个轮播实际上是个很常规的轮播,并非开头所说另类轮播,无论是另类或是常规它的原理,逻辑都是一样的,该学习的是思维,原理,而非具体的写法。