js + translateX 实现无缝滚动轮播图

351 阅读1分钟

最近项目中又使用到了无缝滚动轮播图,太久没写过了。有点遗忘了。 为了方便以后使用,将实现的方式简单的记录下。

   // html部分
   <!-- 视角区域 -->
  <div class="box"><!-- 整体图片区域 -->
    <div class="wipper">
      <div><img src="../imgs/img01.jpg" alt="img" srcset=""></div>
      <div><img src="../imgs/img02.jpg" alt="img" srcset=""></div>
      <div><img src="../imgs/img03.jpg" alt="img" srcset=""></div>
      <div><img src="../imgs/img04.jpg" alt="img" srcset=""></div>
      <div><img src="../imgs/img05.jpg" alt="img" srcset=""></div><!-- 复制第一张图片,后面使第一张和最后一张无缝切换 -->
      <div><img src="../imgs/img01.jpg" alt="img" srcset=""></div>
    </div><!-- 向左切换按钮 -->
    <div class="pre">&lt;</div><!-- 向右切换按钮 -->
    <div class="next">&gt;</div><!-- 底部小圆点 -->
    <div class="lis"><span class="active"></span><span></span><span></span><span></span><span></span></div>
  </div>
   // css 部分
  <style>
    *{
       margin: 0;
       padding: 0;
     }

    .box {
      width: 600px;
      height: 300px;
      margin: 50px auto;
      overflow: hidden;
      position: relative;
    }

    .wipper {
      width: 3600px;
      /*设置为图片的总宽度*/
      height: 300px;
      position: absolute;
      left: 0;
    }

    .wipper div {
      width: 600px;
      height: 300px;
      float: left;
      text-align: center;
      font-size: 30px;
      line-height: 300px;
      color: #fff;
    }

    .pre,
    .next {
      width: 20px;
      height: 30px;
      line-height: 30px;
      text-align: center;
      color: #fff;
      background-color: rgba(0, 0, 0, 0.5);
      position: absolute;
      transform: translateY(-50%);
      cursor: pointer;
      display: none;
    }

    .box:hover .pre {
      display: block;
    }

    .box:hover .next {
      display: block;
    }

    .pre {
      left: 0;
      top: 50%;
    }

    .next {
      right: 0;
      top: 50%;
    }

    .lis {
      text-align: center;
      border-radius: 5px;
      position: absolute;
      bottom: 0;
      left: 50%;
      transform: translateX(-50%);
    }

    .lis span {
      display: inline-block;
      width: 10px;
      height: 10px;
      border-radius: 50%;
      background-color: #ccc;
    }

    .lis span.active {
      background-color: greenyellow;
    }
  </style>

   // js部分
    window.onload = () => {
        //获取元素
        const box = document.getElementsByClassName('box')[0]
        const wipper = document.getElementsByClassName('wipper')[0]
        const divs = wipper.getElementsByTagName('div')
        const pre = document.getElementsByClassName('pre')[0]
        const next = document.getElementsByClassName('next')[0]
        const lis = document.getElementsByClassName('lis')[0]
        const spans = lis.getElementsByTagName('span')
        //定义一个index保存当前图片索引
        let index = 0
        //下一张按钮点击事件
        function nextClick() {
          //点击时index自增
          index++
          //给盒子过渡效果,向左移动
          wipper.style.transition = 'all 1s'
          wipper.style.transform = 'translateX(' + (-index * divs[0].offsetWidth) + 'px)';
          //判断如果到了最后一张
          if (index == divs.length - 1) {
            //初始化index=0
            index = 0
            //设置定时器把最后一张变为第一张
            setTimeout(() => {
              wipper.style.transform = 'translate(0,0)';
              wipper.style.transition = 'none'
            }, 1000);
            //定时器时间设置为500毫秒,与过渡时间相等
          }
          //小圆点变化
          for (var i = 0; i < spans.length; i++) {
            //初始化类名
            spans[i].className = ''
            //给相应图片对应的小圆点添加类名修改颜色
            spans[index].className = 'active'
          }
        }
        next.onclick = nextClick
        //上一张
        function preClick() {
          //点击时index自减
          index--
          //index自减==-1即第一张图片的上一张
          if (index == -1) {
            //使图片转为最后一张
            wipper.style.transform = 'translateX(' + (-5 * divs[0].offsetWidth) + 'px)';
            wipper.style.transition = 'none'
            //初始化index为倒数第二张
            index = 4
            //初始化点击的过渡效果,使其执行完毕,不设置定时器会事件冲突
            setTimeout(() => {
              wipper.style.transform = 'translateX(' + (-index * divs[0].offsetWidth) + 'px)';
              wipper.style.transition = 'all 1s'
            }, 0);
          } else {
            //正常情况的切换
            wipper.style.transform = 'translateX(' + (-index * divs[0].offsetWidth) + 'px)';
            wipper.style.transition = 'all 1s'
          }
          //小圆点变化
          for (var i = 0; i < spans.length; i++) {
            spans[i].className = ''
            spans[index].className = 'active'
          }
        }
        pre.onclick = preClick
        //自动轮播
        var timer = setInterval(nextClick, 3000);
        //小圆点的点击事件
        for (var i = 0; i < spans.length; i++) {
          //设置自调用函数并传入i值,避免点击时循环已经到了最大值结束
          (function (i) {
            spans[i].onclick = function () {
              //获取当前点击圆点父级元素的所有子元素span
              var allSpans = this.parentNode.children
              //循环遍历,清空所有小圆点的类名
              for (var j = 0; j < allSpans.length; j++) {
                allSpans[j].className = ''
              }
              //给当前点击的小圆点添加类名
              this.className = 'active'
              //将i赋值给index
              index = i
              //设置图片切换到点击的小圆点所对应的图片
              wipper.style.transform = 'translateX(' + (-index * divs[0].offsetWidth) + 'px)';
              wipper.style.transition = 'all 1s'
            }
          })(i)
        }
        // 移入box,清除定时器
        box.onmouseenter = function () { clearInterval(timer) }
        // 移出box,重新调用定时器
        box.onmouseleave = function () { timer = setInterval(nextClick, 1000) }
  }