一、前言
前几日,笔者的朋友参加面试,面试官让手写一个轮播图,顿时懵了......想当初,我的轮播图也是写贼溜,这平时 cv 惯了,谁还记得?于是乎,有了下文......
二、手写轮播图
1、复杂版,用于理解轮播图的逻辑
<!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">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
}
a {
text-decoration: none;
}
li {
list-style: none;
}
.box {
position: relative;
width: 590px;
margin: 100px auto;
}
.focus {
width: 590px;
height: 470px;
}
.prev,
.next {
position: absolute;
top: 0;
bottom: 0;
margin: auto;
display: block;
width: 30px;
height: 30px;
line-height: 30px;
text-align: center;
background-color: rgba(0, 0, 0, 0.3);
font-size: 20px;
font-family: simsun;
color: #fff;
cursor: pointer;
}
.prev {
left: 0;
border-radius: 0 10px 10px 0;
}
.next {
right: 0;
border-radius: 10px 0 0 10px;
}
.dotted {
position: absolute;
left: 0;
right: 0;
bottom: 20px;
margin: auto;
width: 150px;
height: 20px;
}
.dotted ul {
display: flex;
justify-content: space-around;
}
.dotted li {
cursor: pointer;
width: 10px;
height: 10px;
background-color: #fff;
border-radius: 50%;
}
.dotted li.current {
background-color: orange;
}
</style>
</head>
<body>
<div class="box">
<!-- 焦点图 -->
<div class="focus">
<ul>
<li><a href=""><img src="./imges/1.jpg" alt=""></a></img></li>
</ul>
</div>
<!-- 上一页 -->
<div class="prev"><</div>
<!-- 下一页 -->
<div class="next">></div>
<!-- 小圆圈 -->
<div class="dotted">
<ul>
<li class="current"></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
</div>
<script>
// 0.存储图片
let imgArr = [
'./imges/1.jpg',
'./imges/2.jpg',
'./imges/3.jpg',
'./imges/4.jpg',
'./imges/5.jpg',
'./imges/6.jpg',
'./imges/7.jpg',
'./imges/8.jpg']
// 1.获取数据
let prev = document.querySelector('.prev')//上一页
let next = document.querySelector('.next')//下一页
let liList = document.querySelectorAll('.dotted li')//小圆圈//伪数组
let img = document.querySelector('.focus img')//获取大图
let box = document.querySelector('.box')//为后面做铺垫,鼠标移入大盒子,停止轮播
// 2.测试数据是否获取
console.log(prev, next, liList, img, box)
//◆全局变量,图片切换做准备(非常重要)
let index = 0
// 3.注册事件
// 3.1鼠标移入小li
for (let i = 0; i < liList.length; i++) {
liList[i].onmouseenter = function () {
// 图片的 src 重新赋值
img.src = imgArr[i]
// 上一个 li 移除样式
document.querySelector('.dotted li.current').classList.remove('current')
// 当前的 li 添加样式
liList[i].classList.add('current')
// 存储下标(不存储下标的话,每次点击上一页下一页,下标都是从 0 开始)
index=i
}
}
// 3.注册事件
// 3.2点击上一页
prev.onclick = function () {
// 如果是第一张,变成最后一张,否则 index--
if (index == 0) {
index = imgArr.length - 1
}
else {
index--
}
// 图片的 src 重新赋值
img.src = imgArr[index]
// 上一个 li 移除样式
document.querySelector('.dotted li.current').classList.remove('current')
// 当前的 li 添加样式
liList[index].classList.add('current')
}
// 3.注册事件
// 3.3点击下一页
next.onclick = function () {
// 如果是最后一张,变成第一张,否则 index++
if (index == imgArr.length - 1) {
index = 0
} else {
index++
}
// 图片的 src 重新赋值
img.src = imgArr[index]
// 上一个 li 移除样式
document.querySelector('.dotted li.current').classList.remove('current')
// 当前的 li 添加样式
liList[index].classList.add('current')
}
// 3.注册事件
// 3.4每隔3秒自动轮播下一页
let timeID = setInterval(function () {
next.onclick()
}, 3000)
// 3.注册事件
// 3.5鼠标移入大盒子,停止轮播
box.onmouseenter = function () {
clearInterval(timeID)
}
// 3.注册事件
// 3.6鼠标移出大盒子,继续轮播
box.onmouseleave = function () {
timeID = setInterval(function () {
next.onclick()
}, 3000)
}
</script>
</body>
</html>
2、简洁版,优化代码,提高用户体验
- 排他思想样式的变化,可以抽离封装成函数
- 鼠标移入 li 元素 可以做防抖,优化用户体验
- 点击上一页下一页,下标的判断改成三元
<script>
// 0.存储图片
let imgArr = [
'./imges/1.jpg',
'./imges/2.jpg',
'./imges/3.jpg',
'./imges/4.jpg',
'./imges/5.jpg',
'./imges/6.jpg',
'./imges/7.jpg',
'./imges/8.jpg']
// 1.获取数据
let prev = document.querySelector('.prev')//上一页
let next = document.querySelector('.next')//下一页
let liList = document.querySelectorAll('.dotted li')//小圆圈//伪数组
let img = document.querySelector('.focus img')//获取大图
let box = document.querySelector('.box')//为后面做铺垫,鼠标移入大盒子,停止轮播
// 2.测试数据是否获取
console.log(prev, next, liList, img, box)
/* ◆◆◆封装函数 */
let paita = function (flag) {
document.querySelector('.dotted li.current').classList.remove('current')
liList[flag].classList.add('current')
img.src = imgArr[flag]
}
//◆全局变量,图片切换做准备(非常重要)
let index = 0
// 3.注册事件
// 3.1鼠标移入小li
for (let i = 0; i < liList.length; i++) {
// ◆防抖第一步:声明变量存储定时器
let timer = null
liList[i].onmouseenter = function () {
// ◆防抖第二步:移除上次定时器
clearTimeout(timer)
// ◆防抖第三步:开启本次定时器
timer = setTimeout(() => {
// 调用
paita(i)
// 存储下标(不存储下标的话,每次点击上一页下一页,下标都是从 0 开始)
index = i
}, 300)
}
}
// 3.注册事件
// 3.2点击上一页
prev.onclick = function () {
// 如果是第一张,变成最后一张,否则 index--
index == 0 ? index = imgArr.length - 1 : index--
// 调用
paita(index)
}
// 3.注册事件
// 3.3点击下一页
next.onclick = function () {
// 如果是最后一张,变成第一张,否则 index++
index == imgArr.length - 1 ? index = 0 : index++
// 调用
paita(index)
}
// 3.注册事件
// 3.4每隔3秒自动轮播下一页
let timeID = setInterval(function () {
next.onclick()
}, 3000)
// 3.注册事件
// 3.5鼠标移入大盒子,停止轮播
box.onmouseenter = function () {
clearInterval(timeID)
}
// 3.注册事件
// 3.6鼠标移出大盒子,继续轮播
box.onmouseleave = function () {
timeID = setInterval(function () {
next.onclick()
}, 3000)
}
</script>