轮播图实现

头像
ler

实际效果

实现需求:

  • 无缝循环轮播
  • 左右按钮点击切换
  • 底部小圆点指示效果与点击切换

代码部分

HTML代码

<div class="banner">
    <div class="slide">
      <!-- 图片区 -->
      <div class="slide-item">
        <img src="./img/c1.jpg" alt="">
      </div>
      <div class="slide-item">
        <img src="./img/c2.png" alt="">
      </div>
      <div class="slide-item">
        <img src="./img/c3.png" alt="">
      </div>
      <div class="slide-item">
        <img src="./img/c4.png" alt="">
      </div>
      <div class="slide-item">
        <img src="./img/c5.png" alt="">
      </div>
    </div>
    <!-- 底部小圆点 -->
    <div class="dots-container">
      <span class="active"></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
    </div>
    <!-- 左右两侧按钮 -->
    <div class="btn btnPre">&lt;</div>
    <div class="btn btnNext">&gt;</div>
  </div>

CSS代码

.banner {
      position: relative;
      overflow: hidden;
      width: 500px;
      height: 300px;
    }

    /* 清除浮动 */
    .slide::before,
    .slide:after {
      content: ' ';
      display: table;
    }

    .slide::after {
      clear: both;
    }

    .slide-item {
      float: left;
    }

    .btn {
      position: absolute;
      width: 40px;
      height: 40px;
      line-height: 40px;
      border-radius: 50%;
      top: 50%;
      margin-top: -10px;
      background-color: #6363636e;
      color: #fff;
      text-align: center;
      cursor: pointer;
      user-select: none;
      font-size: 20px;
      transition: all .4s;
    }

    .btnPre {
      left: 10px;
    }

    .btnNext {
      right: 10px;
    }

    /* 底部小圆点 */
    .dots-container {
      display: flex;
      justify-content: space-between;
      align-items: center;
      position: absolute;
      left: 50%;
      bottom: 20px;
      margin-left: -50px;
      padding: 0 5px;
      width: 90px;
      height: 15px;
      border-radius: 10px;
      background-color: #40404040;
    }

    .dots-container span {
      display: block;
      border: 4px solid #ddd;
      width: 0;
      height: 0;
      border-radius: 50%;
      transition: width .4s;
      cursor: pointer;
    }

    .dots-container .active {
      width: 5px;
      border-radius: 30%;
      border-color: #fff;
    }

JavaScript代码

function $(cName) {
  return document.getElementsByClassName(cName);
}
// 获取元素
const banner = $('banner')[0],
  slide = $('slide')[0],
  slideItem = $('slide-item'),
  btnPre = $('btnPre')[0],
  btnNext = $('btnNext')[0],
  span = $('dots-item');

// 在头部增加一张图,在末尾增加一张图
slide.insertBefore(slideItem[slideItem.length - 1].cloneNode(true), slideItem[0]);
slide.appendChild(slideItem[1].cloneNode(true));
slide.style.width = `${(slideItem.length) * 500}px`; // 定义图片项目容器总宽度,每张图宽度为500
slide.style.transform = 'translateX(-500px)';

let index = 1, // 定义图片下标,第一张index为1
  timer, timer2,
  duration = 'transform .3s'; // 定义动画过度

// 右侧按钮
btnNext.onclick = function () {
  resetDots();
  if (index > slideItem.length - 2) { // 处理滚动到尾部
    index = 1;
    slide.style.transition = 'none';
    slide.style.transform = `translateX(-${index * 500}px)`; // 将整个slide移至视觉第一张位置,即实际第二张
    timer = setTimeout(() => { // 定时延迟确保以上两步操作先完成执行
      slide.style.transition = duration;
      slide.style.transform = `translateX(-${++index * 500}px)`; // 打开过渡效果并继续变换位置实现无缝滚动效果
      span[index - 1].className = 'active'; // 设置变换完成后对应小圆点点亮
      clearTimeout(timer);
    }, 16);
  } else {
    slide.style.transition = duration;
    slide.style.transform = `translateX(-${++index * 500}px)`; // 每次滚动
    if (index == slideItem.length - 1) {  // 处理滚动到最后一张即视觉第一张小圆点点亮位置
      span[0].className = 'active';
    } else {
      span[index - 1].className = 'active';
    }
  }
}
// 左侧按钮
btnPre.onclick = function () {
  resetDots();
  if (index < 1) { // 处理滚动到头部
    index = slideItem.length - 2;
    slide.style.transition = 'none';
    slide.style.transform = `translateX(-${index * 500}px)`; // 将整个slide移至视觉最后一张位置,即实际倒数第二张
    timer = setTimeout(() => { // 定时延迟确保以上两步操作先完成执行
      slide.style.transition = duration;
      slide.style.transform = `translateX(-${--index * 500}px)`; // 打开过渡效果并继续变换位置实现无缝滚动效果
      span[index - 1].className = 'active'; // 设置变换完成后对应小圆点点亮
      clearTimeout(timer);
    }, 16);
  } else {
    slide.style.transition = duration;
    slide.style.transform = `translateX(-${--index * 500}px)`; // 每次滚动
    if (index == 0) { // 处理滚动到第一张即视觉最后一张小圆点点亮位置
      span[span.length - 1].className = 'active';
    } else {
      span[index - 1].className = 'active';
    }
  }
}
// 自动循环播放定时器
timer2 = setInterval(() => {
  btnNext.onclick();
}, 3000);

function resetDots() { // 小圆点样式重置方法
  for (let i = 0; i < span.length; i++) {
    span[i].className = '';
  }

function moveDots() { // 底部小圆点点按事件
  for (let i = 0; i < span.length; i++) {
    (function (n) {
      span[n].onclick = function () {
        resetDots();
        span[n].className = 'active';
        slide.style.transition = duration;
        slide.style.transform = `translateX(-${(n + 1) * 500}px)`;
        index = n + 1;
      }
    })(i);
  }
}
moveDots();
// 鼠标移入移出暂停、继续播放循环
banner.addEventListener("mouseover", function () {
  clearInterval(timer2);
});
banner.addEventListener("mouseout", function () {
  timer2 = setInterval(() => {
    btnNext.onclick();
  }, 2000);
});

评论

lernb.com ©2022 |  lernb | Tencent