原生js--手写轮播图

1.原生手写轮播图

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>轮播图</title>
  <style type="text/css">
    * {
      padding: 0;
      margin: 0;
      list-style: none;
      border: 0;
    }

    .all {
      width: 500px;
      height: 200px;
      padding: 7px;
      border: 1px solid #ccc;
      margin: 100px auto;
      position: relative;
    }

    .screen {
      width: 500px;
      height: 200px;
      /* overflow: hidden; */
      position: relative;
    }

    .screen li {
      width: 500px;
      height: 200px;
      overflow: hidden;
      float: left;
    }

    .screen ul {
      position: absolute;
      left: 0;
      top: 0px;
      width: 3000px;
      /* transition: left 1s; */
    }

    .all ol {
      position: absolute;
      right: 10px;
      bottom: 10px;
      line-height: 20px;
      text-align: center;
    }

    .all ol li {
      float: left;
      width: 20px;
      height: 20px;
      background: #fff;
      border: 1px solid #ccc;
      margin-left: 10px;
      cursor: pointer;
    }

    .all ol li.current {
      background: yellow;
    }

    #arr {
      display: none;
    }

    #arr span {
      width: 40px;
      height: 40px;
      position: absolute;
      left: 5px;
      top: 50%;
      margin-top: -20px;
      background: #000;
      cursor: pointer;
      line-height: 40px;
      text-align: center;
      font-weight: bold;
      font-family: '黑体';
      font-size: 30px;
      color: #fff;
      opacity: 0.3;
      border: 1px solid #fff;
    }

    #arr #right {
      right: 5px;
      left: auto;
    }
  </style>
</head>

<body>
  <div class="all" id="box">
    <!-- 可视区域 -->
    <div class="screen">
      <!-- 要运动的ul标签 -->
      <ul>
        <li><img src="images/1.jpg" width="500" height="200" /></li>
        <li><img src="images/2.jpg" width="500" height="200" /></li>
        <li><img src="images/3.jpg" width="500" height="200" /></li>
        <li><img src="images/4.jpg" width="500" height="200" /></li>
        <li><img src="images/5.jpg" width="500" height="200" /></li>
      </ul>
      <ol>
        <!-- 动态创建的小方块,添加在这里,样式已经给写好了-->
      </ol>
    </div>
    <!-- 左右箭头的父盒子 -->
    <div id="arr"><span id="left">&lt;</span><span id="right">&gt;</span></div>
  </div>
  <script>
    /*
    功能分析:
      - 1 小方块点击功能
        - 根据ul中的图片张数进行ol中的小方块结构创建
        - 给默认的第一个创建的li设置类名为 current
        - 设置点击后的效果
          - 按钮变色
          - 设置ul的滚动
            - 通过move函数设置ul的left修改
            - 需要观察出每次按钮点击时要设置的ul的left值(需要观察规律)
              - 规律为:  - 当前按钮索引 * 图片宽度
                - offsetWidth 用于获取元素的宽度
                  - 只读的数值类型
                - 如果需要操作图片的尺寸,推荐使用可视区域的尺寸进行操作

      - 2 左右按钮点击功能
        - 移入移出大盒子时,设置arrBox显示隐藏
          - onmouseover 鼠标移入事件
          - onmouseout 鼠标移出事件
        - 点击左右按钮时,设置ul进行运动
          - 设置一个变量记录滚到可视区域左侧的图片张数
          - ul的left规律:  - 张数 * 图片宽度
          - 左按钮点击,张数-1,右按钮点击,张数+1
        - 设置对应小方块变色
          - 观察后发现,需要设置变色的小方块的索引与count相同
        - 设置左右按钮和小方块功能联动
          - 注意:在小方块的点击事件中添加:将小方块的索引赋值给count

        - 设置循环滚动功能
          - 结构要求:需要添加假的第一张放到ul最后
            - cloneNode();
              - 参数为true,可以复制元素的完整结构
          - 右按钮:
            - 如果当前显示的为假的第一张,点击了右按钮
              - 设置ul的left为0,显示出真的第一张
              - 再进行正常的滚动操作

          - 设置了假的第一张后,如果假的第一张显示时点击了小方块
            - 会从左侧出现12345的某张图
            - 修改方式:
              - 在小方块点击时,检测是否为假的第一张显示
              - 将ul设置left为0,将ul显示到真的第一张的位置,再进行运动
          - 左按钮
            - 当前如果显示真的第一张,又点击了左按钮
              - 将ul抽回到假的第一张显示的位置

      - 3 自动播放功能
        - 实际上就是间隔一段时间(3~5s左右)进行右按钮的点击操作效果
          - 间隔定时器 setInterval()  clearInterval()
          - 通过元素的click()进行事件的触发
        - 当鼠标移动到轮播图上时,自动播放停止
        - 当鼠标移出时,再次进行自动播放
          - 鼠标移入移出在左右箭头显示隐藏时使用过
            - 为了避免覆盖,需要使用addEventListener()
  
  */

    // 实现:
    // 1 获取元素
    var box = document.getElementById('box'); // 大盒子
    var screenBox = box.children[0]; // 可视区域
    var imgWidth = screenBox.offsetWidth; // 获取可视区域宽度作为图片宽度使用
    var ul = screenBox.children[0]; // 运动的ul
    var ulLis = ul.children; // ul中的所有子元素li
    var ol = screenBox.children[1]; // 小方块的父元素
    var olLis = ol.children; // ol中的所有子元素li
    var arrBox = box.children[1]; // 左右箭头父盒子
    var arrLeft = arrBox.children[0]; // 左箭头
    var arrRight = arrBox.children[1]; // 右箭头

    // 2 根据ul中的图片张数创建底部小方块
    for (var i = 0; i < ulLis.length; i++) {
      var li = document.createElement('li');
      li.innerText = i + 1;
      ol.appendChild(li);
    }
    // 3 给创建的第一个小方块设置默认类名current
    olLis[0].classList.add('current');

    // 4 给小方块设置点击事件
    for (i = 0; i < olLis.length; i++) {
      // 给ol中每个li设置自定义属性data-index,用于保存索引
      // olLis[i].setAttribute('data-index', i);
      olLis[i].dataset.index = i;

      olLis[i].onclick = function () {
        // --- 设置假的第一张后添加的功能
        if (count === ulLis.length - 1) {
          ul.style.left = 0;
          // count = 0; // 因为后面设置过对count的赋值,此处不需要写了
        }

        // 4.1 设置点击按钮变色的功能
        for (var i = 0; i < olLis.length; i++) {
          olLis[i].classList.remove('current');
        }
        this.classList.add('current');

        // 4.2 设置ul根据点击的按钮进行运动
        //   - 需要通过自定义属性保存索引
        var target = -this.dataset.index * imgWidth; // 保存目标位置
        //   - 通过move,让ul运动到target的位置即可
        move(ul, target);

        // --- 将当前元素的索引设置给count,让效果联动
        count = this.dataset.index;
      };
    }

    // ----- 左右按钮操作功能 ----- 
    // 1 设置大盒子box移入移出时,箭头arrBox的显示隐藏
    box.addEventListener('mouseover', function () {
      arrBox.style.display = 'block';
    });
    box.addEventListener('mouseout', function () {
      arrBox.style.display = 'none';
    });

    // 2 设置一个变量用于记录滚出去的张数
    var count = 0;

    //  --- 克隆ul中的第一张图,放入到ul最后,设置为假的第一张
    ul.appendChild(ulLis[0].cloneNode(true));

    // 3 设置右按钮点击事件
    arrRight.onclick = function () {
      // --- 如果当前是假的第一张显示时,应当先将ul的left抽回到0,再滚动
      if (count === ulLis.length - 1) {
        ul.style.left = 0;
        // 注意:ul的位置如果发生改变,count值要随之改变
        count = 0;
      }


      // - 设置计数+1
      count++;
      // - 根据count设置ul的运动位置
      var target = -count * imgWidth;
      move(ul, target);

      // - 设置按钮变色
      for (var i = 0; i < olLis.length; i++) {
        olLis[i].classList.remove('current');
      }
      // 设置了假的第一张后,假的第一张显示时应当为按钮1高亮
      if (count === ulLis.length - 1) {
        olLis[0].classList.add('current');
      } else {
        olLis[count].classList.add('current');
      }

    };

    // 4 设置左按钮点击事件
    arrLeft.onclick = function () {
      // 检测当前是否显示第一张
      if (count === 0) {
        ul.style.left = -(ulLis.length - 1) * imgWidth + 'px';
        count = ulLis.length - 1; // 将count更新
      }

      // 基本滚动操作
      count--;
      var target = -count * imgWidth;
      move(ul, target);
      for (var i = 0; i < olLis.length; i++) {
        olLis[i].classList.remove('current');
      }
      olLis[count].classList.add('current');
    };


    // --- 自动播放功能
    // 1 设置定时器,进行自动播放
    var timer = setInterval(function () {
      // 2 调用右按钮的点击事件, 通过click()操作
      arrRight.click();
    }, 3000);

    // 3 鼠标移入时,设置自动播放停止
    //   - 需要给box重复设置onmouseover和onmouseout
    box.addEventListener('mouseover', function () {
      clearInterval(timer);
    });

    box.addEventListener('mouseout', function () {
      // 重新开启时,必须设置给timer,而且必须是全局变量
      timer = setInterval(function () {
        arrRight.click();
      }, 3000);
    });

    /* move函数用于让某个元素移动到指定位置
      - element 是要运动的元素,DOM对象,别写id名或标签名之类的东西
      - target 是目标位置,数值类型
    */
    function move(element, target) {
      // 为了避免元素出现抖动
      clearInterval(element.timer);
      // 设置新运动的定时器操作:
      element.timer = setInterval(function () {
        // 1 获取元素当前的位置
        var current = element.offsetLeft;
        // 2 计算每次要运动的距离(步长)
        var step = (target - current) / 10;
        // 对step计算的结果进行取整,确保至少移动1px
        //   - 根据step的正负设置对应的向上或向下取整操作
        step = step > 0 ? Math.ceil(step) : Math.floor(step);
        // 3 计算新的运动位置
        current += step;
        // 4 设置给元素的left进行运动
        element.style.left = current + 'px';
        // 5 当元素运动到目标位置后,清除定时器
        if (current === target) {
          clearInterval(element.timer);
        }
      }, 20);
    }
  </script>
</body>

</html>
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

别动我代码儿

感谢技术精进的你,加油不负韶华

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值