Skip to content
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">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    html, body {
      height: 100%;
      overflow: hidden;
    }

    .container {
      width: 1226px;
      height: 460px;
      margin: 0 auto;
      position: relative;
      box-sizing: border-box;
      overflow: hidden;
    }

    .container .wrapper {
      position: absolute;
      top: 0;
      left: 0;
      width: 1226px;
      height: 100%;
    }

    .container .wrapper .slide {
      width: 100%;
      height: 100%;
      background: #eee;
      position: absolute;
      z-index: 0;
      opacity: 0;
      transition: opacity .3s linear;
    }

    .container .wrapper .slide img {
      width: 100%;
      height: 100%;
      display: block;
      cursor: pointer;
    }

    .container .pagination {
      width: 400px;
      height: 21px;
      position: absolute;
      right: 38px;
      bottom: 20px;
      text-align: right;
      z-index: 9;
    }

    .container .pagination span {
      width: 8px;
      height: 8px;
      display: inline-block;
      border: 2px solid #fff;
      border-color: hsla(0, 0%, 100%, .3);
      border-radius: 10px;
      background: rgba(0, 0, 0, .4);
      opacity: .8;
      transition: all .2s;
      cursor: pointer;
    }

    .container .pagination span.active {
      background: rgba(255, 255, 255, .4);
      border-color: rgba(0, 0, 0, .4);
      transform: scale(1.2);
    }

    .container .navigation div {
      width: 41px;
      height: 69px;
      display: block;
      position: absolute;
      top: 196px; /* calc(460px / 2 - 69px / 2) */
      background: url('./imgs/pagination.png') no-repeat;
      z-index: 9;
    }

    .container .navigation .button-prev {
      background-position-x: -83px;
    }

    .container .navigation .button-prev:hover {
      background-position-x: 0px;
    }

    .container .navigation .button-next {
      right: 0;
      background-position-x: -124px;
    }

    .container .navigation .button-next:hover {
      background-position-x: -41px;
    }
  </style>
</head>
<body>
  <section class="container">
    <!-- 轮播图 -->
    <div class="wrapper">
      <div class="slide">
        <img src="./imgs/1.jpg" alt="">
      </div>
      <div class="slide">
        <img src="./imgs/2.webp" alt="">
      </div>
      <div class="slide">
        <img src="./imgs/3.webp" alt="">
      </div>
      <div class="slide">
        <img src="./imgs/4.webp" alt="">
      </div>
    </div>

    <!-- 分页器 -->
    <div class="pagination">
      <span class="active"></span>
      <span></span>
      <span></span>
      <span></span>
    </div>

    <!-- 导航按钮 -->
    <div class="navigation">
      <div class="button-prev"></div>
      <div class="button-next"></div>
    </div>
  </section>

  <script>
    const bannerModule = (function () {
      let container = document.querySelector('.container'),
        wrapper = container.querySelector('.wrapper'),
        pagination = container.querySelector('.pagination'),
        navigation = container.querySelector('.navigation')
        slideList = wrapper.querySelectorAll('.slide'),
        paginationList = pagination.querySelectorAll('span'),
        paginationList = Array.from(paginationList),
        prev = navigation.querySelector('.button-prev'),
        next = navigation.querySelector('.button-next'),
        slideListLength = slideList.length,
        paginationListLength = paginationList.length,
        index = 0, // 当前slide索引
        before = null, // 点击分页器跳转时之前图片的索引
        delay = 1000, // 轮播时间
        timer = null // 定时器返回值(定时器有返回值,是一个数字,代表当前是第几个定时器,清除的时候根据这个号码清除)

      // 显示第一张图片
      const showFirst = function showFirst () {
        slideList[index].style['z-index'] = 1
        slideList[index].style.opacity = 1
      }

      // 自动轮播
      const autoPlay = function autoPlay () {
        if (index >= slideListLength - 1) {
          index = 0
          slideList[index].style['z-index'] = 1
          slideList[slideListLength - 1].style['z-index'] = 0
          slideList[index].style.opacity = 1
          slideList[slideListLength - 1].style.opacity = 0
          slideList[index].clientWidth
          paginationFocus()
          return
        }
        index++
        slideList[index].style['z-index'] = 1
        slideList[index - 1].style['z-index'] = 0
        slideList[index].style.opacity = 1
        slideList[index - 1].style.opacity = 0
        // 每次切换都要控制分页器对齐
        paginationFocus()
      }

      // 开始轮播
      const startPlay = function startPlay () {
        timer = setInterval(autoPlay, delay)
      }

      // 分页器对齐
      const paginationFocus = function paginationFocus () {
        paginationList.forEach((item, idx) => {
          if (index === idx) {
            // 选中的添加样式
            item.classList.add('active')
            return
          }
          // 其他的移除样式
          item.classList.remove('active')
        })
      }

      // 鼠标进入容器,停止轮播/鼠标离开容器,开始轮播
      const handleMouse = function handleMouse () {
        container.onmouseenter = function () {
          clearInterval(timer)
        }
        container.onmouseleave = function () {
          startPlay()
        }
      }

      // 点击分页器切换图片
      const handlePagination = function handlePagination () {
        for(let i = 0; i < paginationListLength; i++) {
          let item = paginationList[i]
          item.onclick = function () {
            // 如果点击当前图片的分页器则不做处理
            if (index === i) {
              return
            }
            before = index
            index = i
            slideList[index].style['z-index'] = 1
            slideList[before].style['z-index'] = 0
            slideList[index].style.opacity = 1
            slideList[before].style.opacity = 0
            // 切换完对齐分页器
            paginationFocus()
          }
        }
      }
      
      const handleNavigation = function navigation () {
        // 点击右导航按钮功能和自动轮播的功能一样,都是切换到下一张
        next.onclick = autoPlay

        // 点击左导航按钮切换
        prev.onclick = function () {
          if (index <= 0) {
            index = slideListLength - 1
            slideList[index].style['z-index'] = 1
            slideList[0].style['z-index'] = 0
            slideList[index].style.opacity = 1
            slideList[0].style.opacity = 0
            paginationFocus()
            return
          }
          index--
          slideList[index].style['z-index'] = 1
          slideList[index + 1].style['z-index'] = 0
          slideList[index].style.opacity = 1
          slideList[index + 1].style.opacity = 0
          paginationFocus()
        }
      }

      return {
        init () {
          showFirst()
          startPlay()
          paginationFocus()
          handleMouse()
          handlePagination()
          handleNavigation()
        }
      }
    })()

    bannerModule.init()
</script>
</body>
</html>