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: 1226px;
      height: 100%;
    }

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

    .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;
      z-index: 9;
      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;
      z-index: 9;
    }

    .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>

    <!-- 分页器 -->
    <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
      }
    }

    let $container = $('.container'),
      $slideList = $container.find('.slide'),
      $paginationList = $container.find('.pagination .btn'),
      $prev = $container.find('.navigation .prev'),
      $next = $container.find('.navigation .next'),
      index = 0,
      interval = 1000,
      timer = null,
      temp = null

    // 初始化时显示第一张
    $slideList.eq(index).css({
      zIndex: 1,
      opacity: 1
    })

    // 切换
    const change = function change () {
      let $cur = $slideList.eq(index),
        $prev = $slideList.eq(temp)
      // 控制z-index
      $cur.css('z-index', 1)
      $prev.css('z-index', 0)
      // 控制opacity
      $cur.css({
        opacity: 1,
        transitionDuration: '.3s'
      }).one('transitionend', function () {
        // 监听一次
        $prev.css({
          opacity: 0,
          transitionDuration: '0s'
        })
      })
      // 分页器对齐
      $paginationList.eq(index).addClass('active')
      $paginationList.eq(temp).removeClass('active')
    }

    // 自动切换
    const autoMove = function autoMove () {
      temp = index
      index++
      index >= 4 ? index = 0 : null
      change()
    }

    timer = setInterval(autoMove, interval)

    $container.mouseenter(function () {
      clearInterval(timer)
    }).mouseleave(function () {
      timer = setInterval(autoMove, interval)
    })

    // 点击分页器实现切换
    $paginationList.click(function () {
      let clickIndex = $(this).index()
      if (clickIndex === index) return
      temp = index
      index = clickIndex
      change()
    })

    // 点击导航按钮实现切换
    $next.click(debounce(autoMove, 300, true))
    $prev.click(debounce(function () {
      temp = index
      index--
      index < 0 ? index = 3 : null
      change()
    }, 300, true))
  </script>
</body>
</html>