网页轮播图(功能最全)

布局:
slider > ul > li
slider > arrow > a> img
arrow : z-index:2 ;
注意,ul 里面放着所有轮播图的图片,所以 ul 的宽度必须足够大能够容纳所有图片,这里有4张图片,ul宽度设置为 600%
功能需求:
1,鼠标经过轮播图模块,左右按钮显示,离开隐藏左右按钮
slider.addEventListener("mouseover", function () {
arrowLeft.style.display = "block";
arrowRight.style.display = "block";
});
slider.addEventListener("mouseout", function () {
arrowLeft.style.display = "none";
arrowRight.style.display = "none";
});
2,动态生成小圆圈
①:核心思路:小圆圈的个数要跟图片张数一致
②:所以首先先得到 ul 里面图片的张数(图片放入 li 中,所以就是 li 的个数)
③:利用循环动态生成小圆圈(这个小圆圈要放入 ol 里面)
④:创建节点 createElement("li")
⑤:插入节点:ol.appendChild (li)
⑥:第一个小圆圈需要添加 current 类
var ul = document.querySelector("ul");
var ol = document.querySelector(".circle");
var imgs = ul.children;
for (var i = 0; i < imgs.length; i++) {
document.createElement("li");
ol.appendChild(li);
}
ol.children[0].className = "current";
3, 小圆圈的排他思想
①点击哪个小圆圈,哪个小圆圈就添加 " current " 类
②其余的小圆圈就移除这个 current 类
③注意:我们在刚才生成小圆圈的同时,就可以直接绑定这个点击事件了。
for (var i = 0; i < imgs.length; i++) {
var li = document.createElement("li");
ol.appendChild(li);
li.addEventListener("click", function () {
for (var j = 0; j < ol.children.length; j++) {
ol.children[j].className = " ";
}
this.className = "current";
});
}
ol.children[0].className = "current";
4,点击小圆圈滚动图片
①此时用到 animate动画函数,将 js 文件引入 (注意,因为 index.js 依赖 animate.js,所以, animate.js 要写到 index.js 上面)
②使用动画函数的前提,该元素必须有定位(ul)
③注意是 ul 移动,不是 小 li
④滚动图片的核心算法:点击某个小圆圈,就让图片滚动,小圆圈的索引号乘以图片的宽度 作为 ul 的移动距离
⑤此时需要知道小圆圈的索引号,我们可以下生成小圆圈的时候,给它设置一个自定义属性,点 击的时候获取这个自定义属性即可。
for (var i = 0; i < imgs.length; i++) {
document.createElement("li");
ol.appendChild(li);
li.setAttribute("index", i);
li.addEventListener("click", function () {
for (var j = 0; j < ol.children.length; j++) {
ol.children[j].className = "";
}
this.className = "current";
var index = this.getAttribute("index");
var sliderWidth = slider.offsetWidth;
animate(ul, -index * sliderWidth);
});
}
ol.children[0].className = "current";
5,右侧按钮无缝滚动
①点击右侧按钮一次,就让图片滚动一张
②声明一个变量num , 点击一次,自增 1,让这个变量乘以图片宽度,就是 ul 的滚动距离
③图片无缝滚动原理:
把 ul 第一个 li 复制一份,放到 ul 的最后面,
当图片滚动到克隆的最后一张图片时,让ul快速的,不做动画的跳到最左侧:left 为0,
同时num赋值为0,可以从新开始滚动图片了。
④ 克隆第一张图片
克隆 ul 第一个 li , cloneNode( ) , 加 true 深克隆, 复制里面的子节点,false 浅克隆
添加到 ul 最后面 appendChild()
var imgLast = ul.children[0].cloneNode(true);
ul.appendChild(imgLast);
var num = 0;
arrowRight.addEventListener("click", function () {
if (num == ul.children.length - 1) {
ul.style.left = 0;
num = 0;
}
num++;
animate(ul, -num * sliderWidth);
}); //这里必须是先判断,再加加,再执行
6,小圆圈跟随右侧按钮一起变化
①最简单的 做法是再声明一个变量 circle , 每次点击自增 1,注意,左侧按钮也需要这个变量, 因此要声明全局变量
②但是图片有5张,小圆圈只有4个少一个,必须加一个判断条件,
③如果 circle==4 ,就重新复原为 0
var num = 0;
var circle = 0;
arrowRight.addEventListener("click", function () {
if (num == ul.children.length) {
ul.style.left = 0;
num = 0;
}
num++;
animate(ul, -num * sliderWidth);
circle++; //这里必须是先加加,再判断,再执行
if (circle == ol.children.length) {
circle = 0;
}
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = "";
}
ol.children[circle].className = "current";
});
7,到这一步,还有两个bug 需要解决
①当点击小圆圈让图片播放到第三张,下面的小圆圈停留在第三个(索引号等于2)的时候,点击右侧按钮,发现下一张图片并不是第4张图片,而是第二张图片
②原因就是点击右侧按钮的时候,num值与点击小圆圈时候的 circle 没有关系
③解决方法:点击小圆圈的时候,获取小圆圈当前的索引号,然后把小圆圈当前的索引号 circle 赋给 num ,这样再点击右侧按钮的时候,就可以在 circle 的基础上自增了。
④第二个bug :上面的bug解决之后,点击小圆圈让图片播放到第三张,再点击右侧按钮,图片可以顺利播放到第四张,但是下面的小圆圈却显示在第二个
⑤原因还是因为点击右侧按钮的时候,右侧按钮点击次数的索引号 num 与 之后点击小圆圈的 circle 没有建立联系
⑥解决方案就是,在点击右侧按钮的时候,获取右侧按钮点击次数当前的索引号,然后把当前的索引号赋给 circle,这样再点击小圆圈的时候,就可以在 num 的基础上 自增了。
li.addEventListener("click", function () {
for (var j = 0; j < ol.children.length; j++) {
ol.children[j].className = "";
}
this.className = "current";
var index = this.getAttribute("index");
num = index;
circle = index;
animate(ul, -index * sliderWIdth);
});
8,左侧按钮功能制作,方法:直接将右侧按钮点击事件复制过来,修改里面的参数即可,注意一些参数的修改
arrowLeft.addEventListener(click, function () {
if (num == 0) {
ul.style.left = -(ul.children.length - 1) * sliderWidth + "px";
num = ul.children.length - 1;
}
num--;
animate(ul, -num * sliderWidth);
circle--;
if (circle < 0) {
circle = ol.children.length - 1;
}
for (var i = 0; i < ol.children.length; i++) {
ol.childdren[i].className = " ";
}
ol.children[circle].className = "current";
});
9,代码优化
window.addEventListener("load", function () {
// alert(11);
var slider = document.querySelector(".slider");
var arrowLeft = document.querySelector(".arrow-left");
var arrowRight = document.querySelector(".arrow-right");
var sliderWidth = slider.offsetWidth;
//1,鼠标经过,左右按钮显示,鼠标离开,左右按钮隐藏
slider.addEventListener("mouseover", function () {
arrowLeft.style.display = "block";
arrowRight.style.display = "block";
});
slider.addEventListener("mouseout", function () {
arrowLeft.style.display = "none";
arrowRight.style.display = "none";
});
//2,动态生成小圆圈
var ul = document.querySelector("ul");
var imgs = ul.children;
var ol = document.querySelector(".circle");
for (var i = 0; i < imgs.length; i++) {
var li = document.createElement("li");
li.setAttribute("index", i); //记录当前小圆圈的索引号,通过自定义属性来做
ol.appendChild(li);
//3,小圆圈的排他思想,我们可以直接在生成小圆圈的同时直接绑定点击事件
li.addEventListener("click", function () {
for (var j = 0; j < ol.children.length; j++) {
ol.children[j].className = "";
}
this.className = "current";
//4,点击小圆圈,移动图片,当然移动的是 ul ,ul 的移动距离=小圆圈的索引号乘以图片的宽度,注意是负值
var index = this.getAttribute("index"); //当我们点击了某个小 li ,就拿到当前小 li 的索引号
//var sliderWidth=slider.offsetWidth; 下面右侧按钮点击事件也用到这个值,所以把它放到最上面
num = index; //当我们点击了某个小圆圈,就要把这个小圆圈的索引号给 num
circle = index; //当我们点击了某个小圆圈,就要把这个小圆圈的索引号给circle
animate(ul, -index * sliderWidth);
});
}
ol.children[0].className = "current";
//5,点击右侧按钮,图片滚动一张
var imgLast = ul.children[0].cloneNode(true); //克隆第一张图片
ul.appendChild(imgLast);
var num = 0;
var circle = 0;
arrowRight.addEventListener("click", function () {
if (num == ul.children.length - 1) {
ul.style.left = 0;
num = 0;
}
num++;
animate(ul, -num * sliderWidth);
//6,点击右侧按钮,小圆圈跟随一起变化,可以再声明一个变量控制小圆圈的播放
circle++;
if (circle == ol.children.length) {
circle = 0;
}
// for(var i=0;i < ol.children.length;i++)
// {
// ol.children[i].className="";
// }
// ol.children[circle].className="current";
//这里可以封装成一个circleChange函数
circleChange();
});
//7,点击左侧按钮,图片滚动一张
arrowLeft.addEventListener("click", function () {
if (num == 0) {
// ul.style.left = -(ul.children.length - 1)*sliderWidth + "px";
// num = ul.children.length - 1;
//这里可以优化一下
num = ul.children.length - 1;
ul.style.left = -num * sliderWidth + "px";
}
num--;
animate(ul, -num * sliderWidth);//8,点击左侧按钮,小圆圈跟随一起变化,可以再声明一个变量控制小圆圈的播放
circle--;
if (circle < 0) {
circle = ol.children.length - 1;
}
// for(var i=0;i < ol.children.length;i++)
// {
// ol.children[i].className="";
// }
// ol.children[circle].className="current";
circleChange();
});
function circleChange() {
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = "";
}
ol.children[circle].className = "current";
}
});
10,自动播放功能
①添加一个定时器
②自动播放轮播图,实际就类似于点击了右侧按钮
③此时我们使用手动调用右侧按钮点击事件 arrowRight.click();
④鼠标经过slider就停止定时器
⑤鼠标离开slider就开启定时器
window.addEventListener("load", function () {
// alert(11);
var slider = document.querySelector(".slider");
var arrowLeft = document.querySelector(".arrow-left");
var arrowRight = document.querySelector(".arrow-right");
var sliderWidth = slider.offsetWidth;
//1,鼠标经过,左右按钮显示,鼠标离开,左右按钮隐藏
slider.addEventListener("mouseover", function () {
arrowLeft.style.display = "block";
arrowRight.style.display = "block";
clearInterval(timer);
});
slider.addEventListener("mouseout", function () {
arrowLeft.style.display = "none";
arrowRight.style.display = "none";
timer = setInterval(function () {
arrowRight.click();
}, 1000);
});
//2,动态生成小圆圈
var ul = document.querySelector("ul");
var imgs = ul.children;
var ol = document.querySelector(".circle");
for (var i = 0; i < imgs.length; i++) {
var li = document.createElement("li");
li.setAttribute("index", i); //记录当前小圆圈的索引号,通过自定义属性来做
ol.appendChild(li);
//3,小圆圈的排他思想,我们可以直接在生成小圆圈的同时直接绑定点击事件
li.addEventListener("click", function () {
for (var j = 0; j < ol.children.length; j++) {
ol.children[j].className = "";
}
this.className = "current";
//4,点击小圆圈,移动图片,当然移动的是 ul ,ul 的移动距离=小圆圈的索引号乘以图片的宽度,注意是负值
var index = this.getAttribute("index"); //当我们点击了某个小 li ,就拿到当前小 li 的索引号
//var sliderWidth=slider.offsetWidth; 下面右侧按钮点击事件也用到这个值,所以把它放到最上面
num = index; //当我们点击了某个小圆圈,就要把这个小圆圈的索引号给 num
circle = index; //当我们点击了某个小圆圈,就要把这个小圆圈的索引号给circle
animate(ul, -index * sliderWidth);
});
}
ol.children[0].className = "current";
//5,点击右侧按钮,图片滚动一张
var imgLast = ul.children[0].cloneNode(true); //克隆第一张图片
ul.appendChild(imgLast);
var num = 0;
var circle = 0;
arrowRight.addEventListener("click", function () {
if (num == ul.children.length - 1) {
ul.style.left = 0;
num = 0;
}
num++;
animate(ul, -num * sliderWidth);
//6,点击右侧按钮,小圆圈跟随一起变化,可以再声明一个变量控制小圆圈的播放
circle++;
if (circle == ol.children.length) {
circle = 0;
}
// for(var i=0;i < ol.children.length;i++)
// {
// ol.children[i].className="";
// }
// ol.children[circle].className="current";
circleChange();
});
//7,点击左侧按钮,图片滚动一张
arrowLeft.addEventListener("click", function () {
if (num == 0) {
// ul.style.left = -(ul.children.length - 1)*sliderWidth + "px";
// num = ul.children.length - 1;
num = ul.children.length - 1;
ul.style.left = -num * sliderWidth + "px";
}
num--;
animate(ul, -num * sliderWidth);
//8,点击左侧按钮,小圆圈跟随一起变化,可以再声明一个变量控制小圆圈的播放
circle--;
if (circle < 0) {
circle = ol.children.length - 1;
}
// for(var i=0;i < ol.children.length;i++)
// {
// ol.children[i].className="";
// }
// ol.children[circle].className="current";
circleChange();
});
function circleChange() {
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = "";
}
ol.children[circle].className = "current";
}
//9,自动播放轮播图
var timer = setInterval(function () {
arrowRight.click();
}, 1000);
});
11, 节流阀
①防止轮播图按钮连续点击造成播放过快
②节流阀的目的:当上一个函数动画内容执行完毕,再去执行下一个函数动画,让事件无法连 续触发
③核心实现思路:利用回调函数,添加一个变量来控制,锁住函数和解锁函数
④开始设置一个 var flage=trur;
⑤ if ( flag) { flag=false ; do something } 关闭水龙头
⑥利用回调函数,动画执行完毕, flag = true 打开水龙头
window.addEventListener("load", function () {
// alert(11);
var slider = document.querySelector(".slider");
var arrowLeft = document.querySelector(".arrow-left");
var arrowRight = document.querySelector(".arrow-right");
var sliderWidth = slider.offsetWidth;
//1,鼠标经过,左右按钮显示,鼠标离开,左右按钮隐藏
slider.addEventListener("mouseover", function () {
arrowLeft.style.display = "block";
arrowRight.style.display = "block";
clearInterval(timer);
});
slider.addEventListener("mouseout", function () {
arrowLeft.style.display = "none";
arrowRight.style.display = "none";
timer = setInterval(function () {
arrowRight.click();
}, 1000);
});
//2,动态生成小圆圈
var ul = document.querySelector("ul");
var imgs = ul.children;
var ol = document.querySelector(".circle");
for (var i = 0; i < imgs.length; i++) {
var li = document.createElement("li");
li.setAttribute("index", i); //记录当前小圆圈的索引号,通过自定义属性来做
ol.appendChild(li);
//3,小圆圈的排他思想,我们可以直接在生成小圆圈的同时直接绑定点击事件
li.addEventListener("click", function () {
for (var j = 0; j < ol.children.length; j++) {
ol.children[j].className = "";
}
this.className = "current";
//4,点击小圆圈,移动图片,当然移动的是 ul ,ul 的移动距离=小圆圈的索引号乘以图片的宽度,注意是负值
var index = this.getAttribute("index"); //当我们点击了某个小 li ,就拿到当前小 li 的索引号
//var sliderWidth=slider.offsetWidth; 下面右侧按钮点击事件也用到这个值,所以把它放到最上面
num = index; //当我们点击了某个小圆圈,就要把这个小圆圈的索引号给 num
circle = index; //当我们点击了某个小圆圈,就要把这个小圆圈的索引号给circle
animate(ul, -index * sliderWidth);
});
}
ol.children[0].className = "current";
//5,点击右侧按钮,图片滚动一张
var imgLast = ul.children[0].cloneNode(true); //克隆第一张图片
ul.appendChild(imgLast);
var num = 0;
var circle = 0;
var flag = true; //flag节流阀
arrowRight.addEventListener("click", function () {
if (flag) {
flag = false; //关闭节流阀
if (num == ul.children.length - 1) {
ul.style.left = 0;
num = 0;
}
num++;
animate(ul, -num * sliderWidth, function () {
flag = true;
});
//6,点击右侧按钮,小圆圈跟随一起变化,可以再声明一个变量控制小圆圈的播放
circle++;
if (circle == ol.children.length) {
circle = 0;
}
// for(var i=0;i < ol.children.length;i++)
// {
// ol.children[i].className="";
// }
// ol.children[circle].className="current";
circleChange();
}
});
//7,点击左侧按钮,图片滚动一张
arrowLeft.addEventListener("click", function () {
if (flag) {
flag = false;
if (num == 0) {
// ul.style.left = -(ul.children.length - 1)*sliderWidth + "px";
// num = ul.children.length - 1;
num = ul.children.length - 1;
ul.style.left = -num * sliderWidth + "px";
}
num--;
animate(ul, -num * sliderWidth, function () {
flag = true;
});
//8,点击左侧按钮,小圆圈跟随一起变化,可以再声明一个变量控制小圆圈的播放
circle--;
if (circle < 0) {
circle = ol.children.length - 1;
}
// for(var i=0;i < ol.children.length;i++)
// {
// ol.children[i].className="";
// }
// ol.children[circle].className="current";
circleChange();
}
});
function circleChange() {
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = "";
}
ol.children[circle].className = "current";
}
//9,自动播放轮播图
var timer = setInterval(function () {
arrowRight.click();
}, 1000);
});
12,完整代码:
①index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
<link rel="stylesheet" href="index.css" />
<script type="text/javascript" src="animate.js"></script>
<script type="text/javascript" src="index.js"></script>
</head>
<body>
<div class="slider">
<a href="javascript:;" class="arrow-left"><</a>
<!--左侧按钮-->
<a href="javascript:;" class="arrow-right">></a>
<!--右侧按钮-->
<ul>
<li>
<a href=""><img src="images/01.jpg" alt="" /></a>
</li>
<li>
<a href=""><img src="images/02.jpg" alt="" /></a>
</li>
<li>
<a href=""><img src="images/03.jpg" alt="" /></a>
</li>
<li>
<a href=""><img src="images/04.jpg" alt="" /></a>
</li>
</ul>
<ol class="circle"></ol>
</div>
</body>
</html>
②index.css
* {
padding: 0;
margin: 0;
}
a {
text-decoration: none;
}
ul,
ol {
list-style: none;
}
.slider {
width: 721px;
height: 455px;
background-color: purple;
margin: 100px auto;
position: relative;
overflow: hidden;
}
.slider > ul {
position: absolute;
top: 0;
left: 0;
width: 600%;
}
.slider > ul >li {
float: left;
}
.arrow-left,
.arrow-right {
width: 24px;
height: 40px;
background-color: rgba(0,0,0,0.3);
position: absolute;
top: 50%;
margin-top: -20px;
z-index: 2;
text-align: center;
line-height: 40px;
color: #fff;
font-size: 20px;
display: none;
}
.arrow-left {
left: 0;
}
.arrow-right {
right: 0;
}
ol.circle {
position: absolute;
bottom: 10px;
left: 50px;
}
.circle > li {
float: left;
width: 8px;
height: 8px;
border: 2px solid rgba(255,255,255,0.5);
margin: 0 3px;
border-radius: 50%;
cursor: pointer;
}
.current {
background-color: #fff;
}
③index.js
window.addEventListener("load", function () {
// alert(11);
var slider = document.querySelector(".slider");
var arrowLeft = document.querySelector(".arrow-left");
var arrowRight = document.querySelector(".arrow-right");
var sliderWidth = slider.offsetWidth;
//1,鼠标经过,左右按钮显示,鼠标离开,左右按钮隐藏
slider.addEventListener("mouseover", function () {
arrowLeft.style.display = "block";
arrowRight.style.display = "block";
clearInterval(timer);
});
slider.addEventListener("mouseout", function () {
arrowLeft.style.display = "none";
arrowRight.style.display = "none";
timer = setInterval(function () {
arrowRight.click();
}, 1000);
});
//2,动态生成小圆圈
var ul = document.querySelector("ul");
var imgs = ul.children;
var ol = document.querySelector(".circle");
for (var i = 0; i < imgs.length; i++) {
var li = document.createElement("li");
li.setAttribute("index", i); //记录当前小圆圈的索引号,通过自定义属性来做
ol.appendChild(li);
//3,小圆圈的排他思想,我们可以直接在生成小圆圈的同时直接绑定点击事件
li.addEventListener("click", function () {
for (var j = 0; j < ol.children.length; j++) {
ol.children[j].className = "";
}
this.className = "current";
//4,点击小圆圈,移动图片,当然移动的是 ul ,ul 的移动距离=小圆圈的索引号乘以图片的宽度,注意是负值
var index = this.getAttribute("index"); //当我们点击了某个小 li ,就拿到当前小 li 的索引号
//var sliderWidth=slider.offsetWidth; 下面右侧按钮点击事件也用到这个值,所以把它放到最上面
num = index; //当我们点击了某个小圆圈,就要把这个小圆圈的索引号给 num
circle = index; //当我们点击了某个小圆圈,就要把这个小圆圈的索引号给circle
animate(ul, -index * sliderWidth);
});
}
ol.children[0].className = "current";
//5,点击右侧按钮,图片滚动一张
var imgLast = ul.children[0].cloneNode(true); //克隆第一张图片
ul.appendChild(imgLast);
var num = 0;
var circle = 0;
var flag = true; //flag节流阀
arrowRight.addEventListener("click", function () {
if (flag) {
flag = false; //关闭节流阀
if (num == ul.children.length - 1) {
ul.style.left = 0;
num = 0;
}
num++;
animate(ul, -num * sliderWidth, function () {
flag = true;
});
//6,点击右侧按钮,小圆圈跟随一起变化,可以再声明一个变量控制小圆圈的播放
circle++;
if (circle == ol.children.length) {
circle = 0;
}
circleChange();
}
});
//7,点击左侧按钮,图片滚动一张
arrowLeft.addEventListener("click", function () {
if (flag) {
flag = false;
if (num == 0) {
num = ul.children.length - 1;
ul.style.left = -num * sliderWidth + "px";
}
num--;
animate(ul, -num * sliderWidth, function () {
flag = true;
});
//8,点击左侧按钮,小圆圈跟随一起变化,可以再声明一个变量控制小圆圈的播放
circle--;
if (circle < 0) {
circle = ol.children.length - 1;
}
circleChange();
}
});
function circleChange() {
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = "";
}
ol.children[circle].className = "current";
}
//9,自动播放轮播图
var timer = setInterval(function () {
arrowRight.click();
}, 1000);
});
④animate.js
function animate(obj, target, callback) {
// console.log(callback); callback = function() {} 调用的时候 callback()
// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function () {
// 步长值写到定时器的里面
// 把我们步长值改为整数 不要出现小数的问题
// var step = Math.ceil((target - obj.offsetLeft) / 10);
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
// 停止动画 本质是停止定时器
clearInterval(obj.timer);
// 回调函数写到定时器结束里面
// if (callback) {
// // 调用函数
// callback();
// }
callback && callback();
}
// 把每次加1 这个步长值改为一个慢慢变小的值 步长公式:(目标值 - 现在的位置) / 10
obj.style.left = obj.offsetLeft + step + "px";
}, 15);
}