手撕轮番图

133 阅读2分钟

轮番图是前端面试常考问题,一般我们在业务中都是直接用现成的库来实现,所以可能比较畏惧手撕轮番图,但实现起来并不复杂。

一、实现内容

图片.png

可以看到:核心元素就是图片、左右两侧按钮、底部按钮,因此需要实现功能如下:

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">&lt;</div>
    <div class="next">&gt;</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);
}