轮番图是前端面试常考问题,一般我们在业务中都是直接用现成的库来实现,所以可能比较畏惧手撕轮番图,但实现起来并不复杂。
一、实现内容
可以看到:核心元素就是图片、左右两侧按钮、底部按钮,因此需要实现功能如下:
1、向左切换
2、向右切换
3、自动向右轮播
4、鼠标移入停止切换
5、点击数字切换
二、核心函数
moveLeft() // 向左切换
moveRight() // 向右切换
autoMove() // 自动播放
stopAutoMove() // 停止自动播放
clickNum() // 点击数字
三、实现
1、HTML
<div class="container">
<ul class="img-ul">
<li class="img-li"><img src="./s01a_10001.jpg"></li>
<li class="img-li"><img src="./s01a_10002.jpg"></li>
<li class="img-li"><img src="./s01a_10003.jpg"></li>
<li class="img-li"><img src="./s01a_10004.jpg"></li>
<li class="img-li"><img src="./s01a_10005.jpg"></li>
</ul>
<div class="prev"><</div>
<div class="next">></div>
<div class="num-box">
<ul class="num-ul">
<li class="num-li" data-index="0">1</li>
<li class="num-li" data-index="1">2</li>
<li class="num-li" data-index="2">3</li>
<li class="num-li" data-index="3">4</li>
<li class="num-li" data-index="4">5</li>
</ul>
</div>
</div>
2、css
ul {
list-style: none;
}
.container {
width: 600px;
height: 400px;
margin: 0 auto;
position: relative;
overflow: hidden;
}
.img-ul {
position: absolute;
display: flex;
width: 3000px;
padding: 0;
}
.img-li {
width: 600px;
}
.img-li > img {
width: 100%;
height: 100%;
object-fit: contain;
}
.prev,
.next {
position: absolute;
width: 40px;
height: 40px;
border-radius: 50%;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
color: #fff;
border: 1px solid #fff;
text-align: center;
line-height: 40px;
}
.prev {
left: 20px;
}
.next {
right: 20px;
}
.num-box {
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: 0;
}
.num-ul {
display: flex;
}
.num-li {
width: 20px;
height: 20px;
border-radius: 50%;
text-align: center;
color:#fff;
border: 1px solid #fff;
margin-left: 3px;
}
3、js
// 获取元素节点
const containerDom = document.getElementsByClassName('container')[0];
const imgUlDom = document.getElementsByClassName('img-ul')[0];
const prevDom = document.getElementsByClassName('prev')[0];
const nextDom = document.getElementsByClassName('next')[0];
const numUlDom = document.getElementsByClassName('num-ul')[0];
const numList = document
.getElementsByClassName('num-ul')[0]
.getElementsByTagName('li');
// 核心逻辑
let currentIndex = 0; // 当前图片
let timer = null;
numList[currentIndex].style.backgroundColor = '#ccc';
prevDom.addEventListener('click', moveLeft);
nextDom.addEventListener('click', moveRight);
containerDom.addEventListener('mouseenter', stopAutoMove);
containerDom.addEventListener('mouseleave', autoMove);
numUlDom.addEventListener('click', clickNum);
autoMove();
// 切换上一张图片
function moveLeft() {
imgUlDom.style.transition = '0.5s';
numList[currentIndex].style.backgroundColor = ''; // 清空上一个按钮的样式
if (currentIndex === 0) {
currentIndex = 4;
} else {
--currentIndex;
}
imgUlDom.style.left = `-${currentIndex * 600}px`;
numList[currentIndex].style.backgroundColor = '#ccc';
}
// 切换下一张图片
function moveRight() {
imgUlDom.style.transition = '0.5s';
numList[currentIndex].style.backgroundColor = '';
if (currentIndex === 4) {
currentIndex = 0;
} else {
++currentIndex;
}
imgUlDom.style.left = `-${currentIndex * 600}px`;
numList[currentIndex].style.backgroundColor = '#ccc';
}
// 数字按钮点击事件
function clickNum(e) {
imgUlDom.style.transition = '0.5s';
let index = e.target.dataset.index;
numList[currentIndex].style.backgroundColor = '';
currentIndex = Number(index);
numList[currentIndex].style.backgroundColor = '#ccc';
imgUlDom.style.left = `-${currentIndex * 600}px`;
}
// 自动轮播
function autoMove() {
timer = setInterval(moveRight, 1000);
}
// 关闭自动轮播
function stopAutoMove() {
clearInterval(timer);
}