轮播图(切换效果)

91 阅读1分钟

index.html文件 Document * { padding: 0; margin: 0; }

        .banner {
            width: 600px;
            height: 400px;
            border: 5px solid black;
            margin: 200px auto;
            /* overflow: hidden; */
            position: relative;
        }

        .banner .img_box {
            width: 500%;
            height: 100%;
            list-style: none;
            display: flex;
            position: absolute;
            left: 0px;
        }

        .banner .img_box li {
            width: 600px;
            height: 100%;
            font-size: 50px;
            text-align: center;
            line-height: 400px;

            display: none;
        }

        .banner .img_box .active {
            display: block;
        }

        .banner .focus {
            width: 200px;
            height: 30px;
            background-color: white;
            position: absolute;
            left: 50%;
            transform: translateX(-50%);
            bottom: 30px;
            border-radius: 20px;
            display: flex;
            justify-content: space-evenly;
            align-items: center;
            list-style: none;
        }

        .banner .focus li {
            width: 20px;
            height: 20px;
            border-radius: 50%;
            background-color: rosybrown;
            cursor: pointer;
        }

        .banner .focus .active {
            background-color: red;
        }

        .left,
        .right {
            position: absolute;
            transform: translateY(-50%);
            font-size: 50px;
            color: white;
            top: 50%;
            cursor: pointer;
        }

        .left {
            left: 30px;
        }

        .right {
            right: 30px;
        }
    </style>
</head>

<body>
    <div class="banner" id="box1">
        <!-- 放置所有轮播图的盒子 -->
        <ul class="img_box">
            <li class="active" style="background-color: burlywood;">1</li>
            <li style="background-color: royalblue;">2</li>
            <li style="background-color: greenyellow;">3</li>
            <li style="background-color: pink;">4</li>
            <li style="background-color: rgb(201, 255, 192);">5</li>
        </ul>
        <!-- 放置焦点的盒子 -->
        <ol class="focus">
            <!-- <li class="active"></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li> -->
        </ol>
        <!-- 左右按钮 -->
        <div class="left">&lt;</div>
        <div class="right">&gt;</div>
    </div>
    <div class="banner" id="box2">
        <!-- 放置所有轮播图的盒子 -->
        <ul class="img_box">
            <li class="active" style="background-color: burlywood;">1</li>
            <li style="background-color: royalblue;">2</li>
            <li style="background-color: greenyellow;">3</li>
            <li style="background-color: pink;">4</li>
            <li style="background-color: rgb(201, 255, 192);">5</li>
        </ul>
        <!-- 放置焦点的盒子 -->
        <ol class="focus">
            <!-- <li class="active"></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li> -->
        </ol>
        <!-- 左右按钮 -->
        <div class="left">&lt;</div>
        <div class="right">&gt;</div>
    </div>
    <script src="./index.js"></script>
    <script>
        const b1 = new Banner('#box1')
        // b1.setFocus()
        // b1.autoPlay()
        // b1.mouseMove()
        // b1.clickBtn()
        new Banner('#box2')
    </script>
</body>
</html>

index.js文件

    /**
     * 面向过程:
     *    1.分析
     *      => 属性(变量)
     *        + banner -> 轮播图可视区域盒子
     *        + imgBox -> 存放图片的 ul
     *        + index -> 表明当前展示的第几张图片
     *        + timer -> 定时器ID
     *      => 方法
     *        + copyEle -> 处理假图
     *        + setFocus -> 设置焦点
     *        + autoplay -> 自动轮播
     * 
     * 面向对象 完成技巧
     *    定义变量 ---> 改成属性 this.xxx = yyy 书写在构造函数的函数体内
     *    定义函数 ---> 改成方法 直接书写在构造函数的原型对象内
     * 
     *    方法内的变量: 如果需要在别的函数内使用,那么将这个变量直接写在 构造函数的函数体内(以前的解决方案是写到全局)
     *                  如果只需要在当前函数内使用,那么直接将这个变量定义在当前函数内
     * */ 
    // function Banner() {}
    class Banner {
      // 构造器,类似于构造函数的函数体
      constructor(ele) {
        this.ele = document.querySelector(ele)
        this.imgBox = this.ele.querySelector('.img_box')
        this.focus = this.ele.querySelector('.focus')

        this.index = 0 //使用下标表示,如果值为0,代表展示第一张图
        this.timer = 0 // 存储定时器ID
        this.init()
      }
      // 以下位置书写原型
      init() {
        this.setFocus()
        this.autoPlay()
        this.mouseMove()
        this.clickBtn()
      }

      // 1. 根据图片数量 设置焦点
      setFocus() {
        // 1.1 获取图片数量
        // console.log(this.imgBox.children.length)
        let liNum = this.imgBox.children.length
        // 1.2 根据图片数量生成焦点
        for(let i = 0; i < liNum; i++) {
          // 1.2.1 创建一个li标签
          const newLi = document.createElement('li')

          // 将下标绑定在标签上
          newLi.dataset.id = i
          // 给每一个li添加一个类名
          newLi.classList.add('focus_item')

          // 1.2.2 添加类名
          i === 0 && newLi.classList.add('active')
          // 1.2.3 插入到DOM视图中
          this.focus.appendChild(newLi)
        }
      }
      // 1.5 重新封装一个类似move函数的方法
      cut(type) {
        /**
         * 1. 点击切换到下一张 (自动切换到下一张)
         * 2. 点击切换到上一张
         * 3. 点击某焦点切换到某一张
         * 
         *  约定:调用cut函数的时候 传递三个不同的参数, 让代码根据参数的不同 做对应的事
         *        如果传递的是true 下一张
         *            传递的是false 上一张
         *            传递的是数字 切换到某一张
         * */ 
        // 1.5.1 函数开始执行,在这里 我们的this。index表示的是当前界面中,哪一个li具有类名,所以可以直接找到它 取消类名
        this.imgBox.children[this.index].classList.remove('active')
        this.focus.children[this.index].classList.remove('active')

        // 1.5.2 根据参数确定一会展示那一张图
        if(type === true) {
          //切换到下一张
          this.index++
        } else if(type === false) {
          //切换到上一张
          this.index--
        } else {
          // 当前分支执行到某一张,具体是哪一张需要根据 参数type的实际值来确定
          this.index = type
        }

        // 边界限制,如果滚动到最后一张,那么下一次应该展示的是 下标0的图片
        if(this.index >= this.imgBox.children.length) {
          this.index = 0
        }
        // 边界限制,如果在第一张,并且需要滚动到上一张,那么实际应该展示的是最后一张
        if(this.index < 0) {
          this.index = this.imgBox.children.length - 1
        }

        // 1.5.3 根据this.index的值 给对应的li添加类名
        this.imgBox.children[this.index].classList.add('active')
        this.focus.children[this.index].classList.add('active')
      }
      // 2. 自动轮播
      autoPlay() {
        this.timer = setInterval(() => {
          // 调用一个类似move函数的方法
          this.cut(true)
        }, 2000)
      }
      // 3. 移入移出事件
      mouseMove() {
        // 3.1 鼠标移入关闭定时器
        this.ele.onmouseover = () => clearInterval(this.timer)
        // 3.2 鼠标移出开启定时器
        this.ele.onmouseout = () => this.autoPlay()
      }
      // 4. 点击事件
      clickBtn() {
        this.ele.onclick = (e) => {
          if(e.target.className === 'left') {
            // 切换上一页
            this.cut(false)
          }

          if(e.target.className === 'right') {
            // 切换下一页
            this.cut(true)
          }

          if(e.target.className === 'focus_item') {
            // 切换某一页
            this.cut(e.target.dataset.id - 0)
          }
        }
      }
    }