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>
  <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
  <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: 6130px; /* calc(1226px * 5); */
      height: 100%;
      transition: left linear;
    }

    .container .wrapper .slide {
      float: left;
      width: 1226px;
      height: 100%;
      background: #eee;
    }

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

    .container .pagination {
      width: 400px;
      height: 21px;
      position: absolute;
      right: 38px;
      bottom: 20px;
      text-align: right;
      user-select: none;
    }

    .container .pagination .btn {
      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 .btn.active {
      background: rgba(255, 255, 255, .4);
      border-color: rgba(0, 0, 0, .4);
      transform: scale(1.2);
    }

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

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

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

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

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

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

    <!-- 导航按钮 -->
    <div class="navigation">
      <a href="javascript:;" class="navigation-btn prev"></a>
      <a href="javascript:;" class="navigation-btn next"></a>
    </div>
  </section>

  <script>
    function debounce (func, wait = 300, immediate = false) {
      let timer = null
      return function anonymouse (...args) {
        let now = immediate && !timer
        // 每次点击都把之前定时器清楚
        clearTimeout(timer)
        // 设置一个新的定时器来监听wait时间内是否有触发第二次
        timer = setTimeout(() => {
          // 手动让其回归到初始状态
          timer = null
          // wait这么久的等待中.没有出发第二次
          !immediate ? func.call(this, ...args) : null
        }, wait)
        // 如果立即执行
        now ? func.call(this, ...args) : null
      }
    }


    const bannerModule = (function () {
      let $container = $('.container'),
        $wrapper = $container.find('.wrapper'),
        $pagination = $container.find('.pagination'),
        $paginationList = $pagination.find('.btn'),
        $navigation = $container.find('.navigation'),
        $prev = $navigation.find('.prev'),
        $next = $navigation.find('.next')

      let index = 0, // slide索引
        interval = 1000, // 轮播时间
        timer = null // 定时器返回值 定时器有返回值,是一个数字,代表当前是第几个定时器,清除的时候根据这个号码清除
  
      // 自动轮播
      const autoMove = function autoMove () {
        if (index >= 4) {
          // 当前显示的是克隆的那一张图片,需要立即运动到真实的第一张
          index = 0
          $wrapper.css('left', 0)
        }

        index++
        $wrapper.stop().animate({
          left: index * -1226
        }, 300)
        // 每次切换都要控制分页器对齐
        paginationFocus()
      }

      // 分页器对齐
      const paginationFocus = function paginationFocus () {
        let temp = index
        temp === 4 ? temp = 0 : null
        $paginationList.each((idx, item) => {
          let $item = $(item)
          if (temp === idx) {
            $item.addClass('active')
            return
          }
          $item.removeClass('active')
        })
      }

      // 点击分页器切换图片
      $paginationList.click(debounce(function () {
        let clickIndex = $(this).index()
        console.log(index)
        if (index === clickIndex || (index === 4 && clickIndex === 0)) return
        index = clickIndex
        $wrapper.stop().animate({
          left: index * -1226
        }, 300)
        paginationFocus()
      }, 300, true))

      // 导航按钮
      const handleNavgation = function handleNavgation () {
        // 点击右导航按钮功能和自动轮播的功能一样,都是切换到下一张
        $next.click(debounce(autoMove, 300, true))
        // 点击左导航按钮切换
        $prev.click(debounce(function () {
          if (index <= 0) {
            index = 4
            $wrapper.css('left', index * -1226)
          }
          index--
          $wrapper.stop().animate({
            left: index * -1226
          }, 300)
          paginationFocus()
        }, 300, true))
      }

      return {
        init () {
          timer = setInterval(autoMove, interval)
          $container.on('mouseenter', function () {
            // 鼠标进入容器,停止轮播
            clearInterval(timer)
          }).on('mouseleave', function () {
            // 鼠标离开容器,开始轮播
            timer = setInterval(autoMove, interval)
          })
          handleNavgation() 
        }
      }
    })()

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