滚动轮播图
在JS初级阶段,轮播图是最基础最经典的案例,而相比于渐变轮播图,无缝滚动轮播图又要更难一点。渐变轮播图仅需要使用到点击事件、定时器等,而无缝滚动轮播图则需要考虑到 第一张>最后一张,最后一张>第一张的滚动切换。
效果图:
需求:
制作一个无缝滚动轮播图,轮播图会自动无缝滚动切换,当鼠标移到轮播图区域停止自动播放,鼠标移出后轮播图继续自动播放,拥有向左、向右点击切换功能和底部小圆点切换功能。
思路:
- 把几张图当成整体放在一个盒子里,使用浮动让所有图片一行排列,盒子宽度为图片宽度之和
- 外面套一层父级盒子设置为一张图的宽度,同时设置溢出隐藏
- 点击左/右切换时运用transform将整体向相应的方向移动
- 自动轮播巧妙运用过渡效果以及定时器的调用与清除
HTML结构
这里给放置图片的区域设置颜色来替代了图片
<!-- 视角区域 -->
<div class="box">
<!-- 整体图片区域 -->
<div class="wipper">
<div style="background-color: red;">1</div>
<div style="background-color: green;">2</div>
<div style="background-color: brown">3</div>
<div style="background-color: blue;">4</div>
<div style="background-color: cadetblue;">5</div>
<!-- 复制第一张图片,后面使第一张和最后一张无缝切换 -->
<div style="background-color: red;">1</div>
</div>
<!-- 向左切换按钮 -->
<div class="pre"><</div>
<!-- 向右切换按钮 -->
<div class="next">></div>
<!-- 底部小圆点 -->
<div class="lis">
<span class="current"></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
</div>
css样式
*{
margin: 0;
padding: 0;
}
.box{
width: 600px;
height: 300px;
margin: 50px auto;
overflow: hidden;
position: relative;
}
.wipper{
width: 3600px;/*设置为图片的总宽度*/
height: 300px;
position: absolute;
left: 0;
}
.wipper div{
width: 600px;
height: 300px;
float: left;
text-align: center;
font-size: 30px;
line-height: 300px;
color: #fff;
}
.pre,.next{
width: 20px;
height: 30px;
line-height: 30px;
text-align: center;
color: #fff;
background-color: rgba(0, 0, 0, 0.5);
position: absolute;
transform: translateY(-50%);
cursor: pointer;
display: none;
}
.box:hover .pre{
display: block;
}
.box:hover .next{
display: block;
}
.pre{
left: 0;
top: 50%;
}
.next{
right: 0;
top: 50%;
}
.lis{
text-align: center;
border-radius: 5px;
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
}
.lis span{
display: inline-block;
width: 10px;
height: 10px;
border-radius: 50%;
background-color: #ccc;
}
.lis span.current{
background-color: greenyellow;
}
JS代码
难点:
如何使图片在第一张时点击上一张,向左滚动切换到最后一张。
如何使图片在最后一张时点击下一张,向右滚动切换到第一张
//获取元素
var box=document.getElementsByClassName('box')[0]
var wipper=document.getElementsByClassName('wipper')[0]
var divs=wipper.getElementsByTagName('div')
var pre=document.getElementsByClassName('pre')[0]
var next=document.getElementsByClassName('next')[0]
var lis=document.getElementsByClassName('lis')[0]
var spans=lis.getElementsByTagName('span')
//定义一个index保存当前图片索引
var index=0
//下一张按钮点击事件
function nextClick(){
//点击时index自增
index++
//给盒子过渡效果,向左移动
wipper.style.transition='all .5s'
wipper.style.transform='translateX('+(-index*divs[0].offsetWidth) +'px)' ;
//判断如果到了最后一张
if(index==divs.length-1){
//初始化index=0
index=0
//设置定时器把最后一张变为第一张
setTimeout(() => {
wipper.style.transform='translate(0,0)' ;
wipper.style.transition='none'
}, 500);//定时器时间设置为500毫秒,与过渡时间相等
}
//小圆点变化
for(var i=0;i<spans.length;i++){
//初始化类名
spans[i].className=''
//给相应图片对应的小圆点添加类名修改颜色
spans[index].className='current'
}
}
next.onclick=nextClick
//上一张
function preClick(){
//点击时index自减
index--
//index自减==-1即第一张图片的上一张
if(index==-1){
//使图片转为最后一张
wipper.style.transform='translateX('+(-5*divs[0].offsetWidth) +'px)' ;
wipper.style.transition='none'
//初始化index为倒数第二张
index=4
//初始化点击的过渡效果,使其执行完毕,不设置定时器会事件冲突
setTimeout(() => {
wipper.style.transform='translateX('+(-index*divs[0].offsetWidth) +'px)' ;
wipper.style.transition='all .5s'
}, 0);
}else{
//正常情况的切换
wipper.style.transform='translateX('+(-index*divs[0].offsetWidth) +'px)' ;
wipper.style.transition='all .5s'
}
//小圆点变化
for(var i=0;i<spans.length;i++){
spans[i].className=''
spans[index].className='current'
}
}
pre.onclick=preClick
//自动轮播
var timer=setInterval(nextClick,1000);
//小圆点的点击事件
for(var i=0;i<spans.length;i++){
//设置自调用函数并传入i值,避免点击时循环已经到了最大值结束
(function(i){
spans[i].onclick=function(){
//获取当前点击圆点父级元素的所有子元素span
var allSpans=this.parentNode.children
//循环遍历,清空所有小圆点的类名
for(var j=0;j<allSpans.length;j++){
allSpans[j].className=''
}
//给当前点击的小圆点添加类名
this.className='current'
//将i赋值给index
index=i
//设置图片切换到点击的小圆点所对应的图片
wipper.style.transform='translateX('+(-index*divs[0].offsetWidth) +'px)' ;
wipper.style.transition='all .5s'
}
})(i)
}
// 移入box,清除定时器
box.onmouseenter=function(){
clearInterval(timer)
}
// 移出box,重新调用定时器
box.onmouseleave=function(){
timer=setInterval(nextClick,1000)
}