思路
无缝切换
假设这是图片数组[0,1,2,3,4] 共5张图片,index是4的时候点击下一张,要切换成第1张,而不是从4->3->2->1->0这样滚回去,也就是说其实是这样的效果 [0,1,2,3,4,0] 实现4->0的无缝切换。
从0->4也是同样的道理,0在点击上一张的时候,瞬间切换到4后面的0,然后再切换到4.
节流
防抖简单来说就是打断回城,需要重新回城,
节流就是cd。
当最后一张图片切换到第一张图片时,快速点击会出现闪屏的现象,因此可以限制点击速率来实现。 设置一个lock变量,点击后值设置为false,在点击xx毫秒后再设置true。使用setTimeout实现
代码
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<title>轮播图</title>
</head>
<body>
<!-- 容器 -->
<div class="box">
<!-- 图片列表 -->
<div class="img-list">
<img src="pic/1.png" alt="">
<img src="pic/2.png" alt="">
<img src="pic/3.png" alt="">
<img src="pic/4.png" alt="">
<img src="pic/5.png" alt="">
</div>
<!-- 小箭头 -->
<div class="arrow">
<a href="javascript:;" class="left"><</a>
<a href="javascript:;" class="right">></a>
</div>
<!-- 小圆点 -->
<ul class="circle-list">
<li class="circle" data-n="0"></li>
<li class="circle" data-n="1"></li>
<li class="circle" data-n="2"></li>
<li class="circle" data-n="3"></li>
<li class="circle" data-n="4"></li>
</ul>
</div>
<script src="./main.js"></script>
</body>
</html>
css
* {
margin: 0;
padding: 0;
}
ul {
list-style: none;
}
.box {
overflow: hidden;
position: relative;
width: 1024px;
height: 580px;
margin: 100px auto 0;
}
.box .img-list {
display: flex;
position: relative;
left: 0px;
width: 100%;
height: 100%;
transition: 0.5s ease;
}
.box .img-list img {
width: 100%;
cursor: pointer;
}
.box a {
position: absolute;
top: 50%;
transform: translate(0,-50%);
display: block;
width: 40px;
height: 70px;
background: rgba(0,0,0,0.7);
color: white;
user-select: none;
font-size: 30px;
text-align: center;
line-height: 70px;
text-decoration: none;
}
.box a.left {
left: 0;
}
.box a.right {
right: 0;
}
.circle-list {
display: flex;
position: absolute;
bottom: 20px;
left: 50%;
transform: translate(-30%,0);
width: 240px;
height: 40px;
z-index: 99;
}
.circle-list li{
cursor: pointer;
}
.circle-list > .circle {
margin: 0 5px;
width: 25px;
height: 25px;
background-color: #ecf0f1;
border-radius: 50%;
}
.circle-list > .circle.active {
/* background-color: #154599; */
background-color: #e74c3c;
}
javascript
// 如何实现?
// 1.最外层盒子包裹
// 2.图片移动动画
// 3.点击事件
// 4.小圆点
// 获取左右按钮和图片列表
let btnLeft = document.querySelector('.left');
let btnRight = document.querySelector('.right');
let imgList = document.querySelector('.img-list');
// 图片索引
let index = 0;
// 复制第一张图片到最后面
let cloneFirstImg = imgList.firstElementChild.cloneNode();
imgList.appendChild(cloneFirstImg);
// 获取小圆点的数组
const circles = document.querySelectorAll('.circle');
// 设置函数节流锁
let lock = true;
// 小圆点点击切换图片 使用事件代理
const oCircle = document.querySelector('.circle-list');
// 自动轮播
let autoPlay = setInterval(setRightGo, 2000);
// 获取轮播图的区域
const obox = document.querySelector('.box');
// 首次添加小圆点
setCircles();
// 往右切换下一张
function setRightGo() {
if(!lock) return;
index++;
imgList.style.left = index * -1024 + 'px';
// 加回过度效果
imgList.style.transition = '0.5s ease';
// 也就是 下一张是 '第一张'
if(index===5) {
index = 0;
setTimeout(() => {
imgList.style.left = 0;
imgList.style.transition = 'none';
// 这里是因为过度动画是0.5s 所以这里也是0.5s,相当于藏起来
},500);
}
// 设置小圆点高亮
setCircles();
// 关锁
lock = false;
setTimeout(() => {
lock = true;
},500);
}
// 右按钮
btnRight.addEventListener('click',setRightGo);
// 左按钮也是一样
btnLeft.addEventListener('click',(e) => {
if(!lock) return;
index--;
if(index === -1) {
// 首先 瞬间切换到第六张假图、也就是伪装的第一张图片
// 并且不需要过度动画
imgList.style.left = 5 * -1024 + 'px';
imgList.style.transition = 'none';
index = 4;
// 然后进行异步操作,然后过渡到第五张
setTimeout(() => {
imgList.style.left = index * -1024 + 'px';
// 加上动画
imgList.style.transition = '0.5s ease';
},0);
}else {
imgList.style.left = index * -1024 + 'px';
}
// 设置小圆点高亮
setCircles();
// 关锁
lock = false;
setTimeout(() => {
lock = true;
}, 500);
})
// 小圆点高亮显示
function setCircles() {
for (let i=0;i<circles.length;i++) {
if(i === index) {
circles[i].classList.add('active');
}else {
circles[i].classList.remove('active');
}
}
}
oCircle.addEventListener('click',(e) => {
if(e.target.nodeName.toLowerCase() === 'li') {
// 当前元素的 data-n 的值
const n = (Number(e.target.getAttribute('data-n')));
index = n;
imgList.style.left = index * -1024 + 'px';
setCircles();
}
})
// 移入关闭定时器
obox.addEventListener('mouseenter',() => {
clearInterval(autoPlay);
})
// 移出开启定时器
obox.addEventListener('mouseleave',() => {
// 设表先关,设置定时器前,先清除
clearInterval(autoPlay);
autoPlay = setInterval(setRightGo, 2000);
})