首先确定需求。
做一个仿照淘宝首页的轮播图有以下需求:
①.鼠标经过轮播图模块,左右按钮显示,离开隐藏左右按钮。
②.点击右侧按钮一次,图片往左播放一张,以此类推,左侧按钮同理。
③.图片播放的同时,下面小圆圈模块跟随一起变化。
④.点击小圆圈,可以播放相应图片。
⑤.鼠标不经过轮播图,轮播图也会自动播放图片。
⑥.鼠标经过,轮播图模块, 自动播放停止。
确定需求之后先用HTML和CSS把结构搭建好,这个案例重点在于JavaScript的操作。
我在写代码的时候注释的都比较详细了,在这里就不讲了。
这个案例的主要js文件如下:
//让Window的结构加载完再执行JS
window.addEventListener ('load',function(){
var arr_l = document.querySelector(".arr_l");
var arr_r = document.querySelector(".arr_r");
var focus = document.querySelector(".focus");
var t= null;
var num = 0;
t = setInterval(function(){
arr_r.click();
},1000);
//①第一个功能:鼠标离开时隐藏两侧图标,鼠标进入时显示
focus.addEventListener("mouseenter",function(){
arr_l.style.display = "block";
arr_r.style.display = "block";
//当鼠标经过时,让它停止自动播放,即隔清除计时器
clearInterval(t);
t = null;
});
focus.addEventListener("mouseleave",function(){
arr_l.style.display = "none";
arr_r.style.display = "none";
//当鼠标离开时,让它自动播放,即隔一段时间调用一下点击右侧时间
t = setInterval(function(){
arr_r.click();
},1000);
});
//②动态生成小圆圈,使它和图片的数目一致
//③点击小圆圈,当前小圆圈变实心。用排他思想
var lis = document.querySelectorAll(".box li");
var box = document.querySelector(".box");
var circle = document.querySelector(".circle");
for(var i=0;i<lis.length;i++){
var li = document.createElement("li");
li.setAttribute("data_index",i);
li.addEventListener("click",function(){
for(var i = 0;i<circle.children.length;i++){
circle.children[i].className = "";
}
this.className = "current";
//④点击圆圈图片滑动
var index = this.getAttribute("data_index")
var target = -index * box.children[0].clientWidth;
animate(box,target);
});
circle.appendChild(li);
}
//默认第一个圆圈为实心
circle.children[0].className = "current";
/*
* 为了让最后一张图片跳到第一张图片的时候更顺畅,可以把第一张图片复制到第四张的后面
* 如果在最后一张的时候点击了后一张,那么显示复制的那张图片,而小圆圈变成第一个
* 这样看起来会跟连贯,像一个循环一样
*/
var first = box.children[0].cloneNode(true);
box.appendChild(first);
/*
* 设置一个num值,每次点击加1.从而每次点击的目标位置就是-num* box.children[0].clientWidth
*/
var cir = 0; //用cir来控制小圆圈变化
//注册右侧按钮事件
/*
* 这里为了防止点击过快导致播放过快,要设置一个节流阀,让上一个动画执行完毕才能开始下一个动画。
*/
var flag = true;
arr_r.addEventListener("click",function(){
/*
* 当num=box.children.length-1 时,即图片播放到了最后一张。
* 当已经播放到最后一张时,此时若右侧按钮再被点击,
* 则马上让num=0,让box的lfet值设为0,让它显示第一张图片。
* 但是后面还会执行一次animate(box,-num * box.children[0].clientWidth);
* 所以播放起来就会像是一个循环
*/
if(flag){
flag = false; //关闭节流阀
if(num==box.children.length-1){
box.style.left = 0;
num = 0;
}
num++;
//在动画函数的回调函数里把节流阀打开,这样确保是在动画完毕后,才能开始下一个动画
animate(box,-num * box.children[0].clientWidth,function(){
flag = true;
});
//点击按钮让图片滑动时,应该让小圆圈也对应显示
cir++;
if(cir == circle.children.length){
cir=0;
}
changeCircle();
}
});
//注册左侧事件
arr_l.addEventListener("click",function(){
if(flag){
flag=false;
if(num==0){
box.style.left = box.children.length-1;
num = box.children.length-1;
}
num--;
animate(box,-num * box.children[0].clientWidth,function(){
flag=true;
});
//点击按钮让图片滑动时,应该让小圆圈也对应显示
cir--;
if(cir<0){
cir=circle.children.length-1;
}
changeCircle();
}
});
/*
* 控制小圆圈变化的函数
*/
function changeCircle(){
for(var i = 0;i<circle.children.length;i++){
circle.children[i].className = "";
}
circle.children[cir].className = "current";
}
});
还有一个滑动动画的函数放在这个文件夹里:
function animate(obj,target,callback){
//在每次点击时先清除上一次的计时器,这样就不会出现连续点击会让盒子走的太快
clearInterval(obj.timer);
obj.timer = setInterval(function(){
var step = (target - obj.offsetLeft) / 5;
step = step > 0 ? Math.ceil(step) : Math.floor(step);//给每一步的距离取整,避免出现小数,导致最后终点和target不一样
obj.style.left = obj.offsetLeft + step + "px";
if(obj.offsetLeft==target){
clearInterval(obj.timer);
callback && callback();//如果有callback则执行,没有则不执行
}
},50);
}
最后的运行结果如下:
轮播图效果
(PS如果有需要源文件的小伙伴可以私信我)