纯JS实现轮播图(点击按钮切换下一张)

  • 可控制是否自动轮播
  • 左右箭头切换上一张,下一张,节流处理
  • 鼠标放到箭头上,图片停止自动轮播,鼠标移开接着继续播放
  • 点击小圆点可跳转到对应顺序的图片
  • 移动端可左滑、右滑切换

1.gif

实现思路:

image.png

html代码:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>轮播图</title>
    <link rel="stylesheet" href="css/轮播图.css">
    <script src="js/轮播图.js"></script>
  </head>
  <body>
    <div class="wrapper">
      <a href="javascipt:;" class="prev"></a>  //href=''可实现不跳转的功能
      <ul class="img_wrapper">
        <li><img src="img/img1.jpg"></img></li>
        <li><img src="img/img2.jpg"></img></li>
        <li><img src="img/img3.jpg"></img></li>
        <li><img src="img/img4.jpg"></img></li>
        <li><img src="img/img5.jpg"></img></li>
        <li><img src="img/img6.jpg"></img></li>
      </ul>
      <a href="javascipt:;" class="next"></a>
      <ul class="circle">  //这里是存放小圆圈,在js会根据图片的数量来添加
      </ul>
    </div>
  </body>
</html>

复制代码

css代码:

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
ul {
  list-style: none;
}
.wrapper {
  position: relative;
  width: 500px;
  height: 350px;
  background-color: pink;
  margin: 100px auto;
  overflow: hidden;  //只显示一张图片,其余图片隐藏
}
.img_wrapper {
  position: absolute;   //使用绝对定位要记住“子绝父相”(子元素使用绝对定位,父元素则使用相对定位)
  top: 0;
  width: 0;
  width: 700%; //这里注意不是一张图片的宽度,而是全部图片的宽度,使这个图片的盒子能刚好装下所有图片
  height: 350px;
}
.img_wrapper > li {
  float: left;  //向左浮动使图片盒子li一行排列并且没有空隙
  width: 500px;
  height: 350px;
}
.img_wrapper > li > img {
  width: 500px;   //让图片的宽高等于父盒子的父盒子的宽高
  height: 350px;
}
.wrapper > a {   //这是上一张图片和下一张图片按钮的共同属性
  position: absolute;
  top: 50%;
  width: 35px;
  height: 35px;
  margin-top: -17.5px;
  background-color: rgba(0, 0, 0, 0.3);
  z-index: 3;
  display: none;
}
.prev {
  left: 0;
  background: url("../img/prev.png") no-repeat center;
}
.next {
  right: 0;
  background: url("../img/next.png") no-repeat center;
}
.circle {
  position: absolute;
  display: flex;
  justify-content: space-between;
  align-items: center;
  bottom: 10px;
  left: 50%;
  background-color: rgba(245, 245, 245, 0.4);
  padding: 2px 5px;
  border-radius: 5px;
}
.circle > li {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  border: 1px solid white;
  margin: 0 3px;
  cursor: pointer;
}
.current {   //这个属性是给小圆圈添加的,当前图片对应的小圆圈背景变为白色
  background-color: white;
}

复制代码

js代码:

window.addEventListener("DOMContentLoaded", function () {  
  var wrapper = document.querySelector(".wrapper");
  var prev = document.querySelector(".prev");
  var next = document.querySelector(".next");
  var img_wrapper = document.querySelector(".img_wrapper");
  var circle = document.querySelector(".circle");
  //flag是用来判断上一个动画是否已经完成,完成才能进行下一个动画(这里的动画指图片左右滑动的动画)
  var flag = true;  
  var num = 0;  //num用于判断是第几张图片
  var timerA = setInterval(() => {  //这个定时器实现自动播放下一张图片的效果
    next.click();  //自动播放下一张不是直接改变这个盒子的位移,而是通过点击next按钮
  }, 1500);
  
  //利用for循环生成circle
  for (var i = 0; i < img_wrapper.children.length; i++) {
    var li = document.createElement("li");
    circle.appendChild(li);
    //使用setAttribute给小圆圈添加index这个自定义属性,并且赋值,以便后续通过index获取当前是第几张图片
    li.setAttribute("index", i);
    li.addEventListener("click", function () {
      for (var j = 0; j < circle.children.length; j++) {
        circle.children[j].className = "";
      }
      this.className = "current";  //每次点击小圆圈则该小圆圈变成白色,其余颜色变为透明(排他思想)
      
      num = this.getAttribute("index");
      animate(  //实现点击小圆圈也可以切换图片
        img_wrapper,
        -img_wrapper.parentElement.offsetWidth * this.getAttribute("index")
      );
    });
  }
  
//由于播放到最后一张图片后再点击下一张图片动画会返回第一张,并且画面非常不好看,要实现无缝切换图片即需将第一张图片复制放到最后面。由于添加小圆圈的代码是在复制第一张图片之前执行的,因此小圆圈的数量不会受影响。

  var firstImg = img_wrapper.children[0].cloneNode(true);//创建节点
  img_wrapper.appendChild(firstImg);//添加节点
  var circleLis = circle.querySelectorAll("li");//将所有小圆圈添加到数组里
  circleLis[0].className = "current";//默认第一个小圆圈为当前状态
  
  //由于在css中left是50%,因此不是居中的状态,当我们把圆圈添加后获取整个盒子的长度,使marginLeft等于负的盒子的一半即可实现居中效果
  circle.style.marginLeft = -(circle.offsetWidth / 2) + "px";

//当我们鼠标不在图片的盒子中时,不显示切换图片的两个按钮,这里实现鼠标在盒子上方时按钮显示,并且暂停自动播放图片的功能
  wrapper.addEventListener("mouseenter", function () {
    prev.style.display = "block";
    next.style.display = "block";
    clearInterval(timerA);  //清除定时器,暂停自动播放的功能
    timerA = null;
  });
  
  //鼠标离开盒子上方,按钮隐藏,开始自动播放的功能
  wrapper.addEventListener("mouseleave", function () {
    prev.style.display = "none";
    next.style.display = "none"; 
    timerA = setInterval(() => {  //添加定时器,开始自动播放的功能
      next.click();
    }, 1500);
  });

  next.addEventListener("click", function () {
    if (flag) {  //flag判断是否上一个动画已完成
      flag = false;//当开始这一次的动画(切换图片)时,使flag为false,这样再点击按钮就不会开始下一个动画
      //判断是否是最后一张图片,最后一张图片与第一张图片一样,如果已经是最后一张图片了,使图片盒子的left值立即回到0,即初始位置,这样在切换下一张图片时就会切换到第二张图片
      if (num == img_wrapper.children.length - 1) {
        img_wrapper.style.left = 0 + "px";
        num = 0;
      }
      num++;

      animate(
        img_wrapper,
        -num * img_wrapper.parentElement.offsetWidth,
        function () {
          flag = true;
        }
        
        //动画结束,使flag=true
      );
        //这里改变小圆圈的背景颜色,使小圆圈的背景颜色随着图片的切换而改变
      for (var i = 0; i < circleLis.length; i++) {
        circleLis[i].className = "";

        if (num == img_wrapper.children.length - 1) {  
        //当图片是最后一张时,第一个小圆圈改变背景颜色
          circleLis[0].className = "current";
        } else {
          circleLis[num].className = "current";
        }
      }
    }
  });
//上一张图片的按钮代码与下一张的相似
  prev.addEventListener("click", function () {
    if (flag) {
      if (num == 0) {
        num = img_wrapper.children.length - 1;
        img_wrapper.style.left =
          -num * img_wrapper.parentElement.offsetWidth + "px";
      }
      num--;
      animate(
        img_wrapper,
        -num * img_wrapper.parentElement.offsetWidth,
        function () {
          flag = true;
        }
      );

      for (var i = 0; i < circleLis.length; i++) {
        circleLis[i].className = "";
        circleLis[num].className = "current";
      }
    }
  });
//切换图片的动画
//obj:目标盒子,target:需要移动的距离
  function animate(obj, target, callback) {
    clearInterval(obj.timer);//首先先清除定时器,防止过多定时器的叠加
    
    obj.timer = setInterval(() => {
      if (obj.offsetLeft == target) {//当目标盒子的left值等于目标距离时清除定时器
        clearInterval(obj.timer);
        // if (callback) {
        //   callback();
        // }相当于:
        callback && callback();
      } else {
        obj.step = (target - obj.offsetLeft) / 10;  //这行代码可以实现变速的移动,不懂的自己代入数值计算
        if (obj.step >= 0) {
          obj.step = Math.ceil(obj.step);
        } else {
          obj.step = Math.floor(obj.step);
        }

        obj.style.left = obj.offsetLeft + obj.step + "px";
      }
    }, 15);
  }
});

复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享