web技术

原生js实现轮播图

2023-07-18 06:24 作者:Admin

很多网站上都有轮播图,但却很难找到一个系统讲解的,因此这里做一个简单的介绍,希望大家都能有所收获,如果有哪些不正确的地方,希望大家可以指出。

github地址(如果有用,就star一下吧):https://github.com/zzw918/swiper

原理:

将一些图片在一行中平铺,然后计算偏移量再利用定时器实现定时轮播。

步骤一:建立html基本布局

如下所示:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>轮播图</title>
  </head>
  <body>
    <div class="container">
      <div class="wrap" style="left: -600px">
        <img src="./img/5.jpg" alt="" />
        <img src="./img/1.jpg" alt="" />
        <img src="./img/2.jpg" alt="" />
        <img src="./img/3.jpg" alt="" />
        <img src="./img/4.jpg" alt="" />
        <img src="./img/5.jpg" alt="" />
        <img src="./img/1.jpg" alt="" />
      </div>
      <div class="buttons">
        <span>1</span>
        <span>2</span>
        <span>3</span>
        <span>4</span>
        <span>5</span>
      </div>
      <a href="javascript:;" class="arrow arrow_left"><</a>
      <a href="javascript:;" class="arrow arrow_right">></a>
    </div>
  </body>
</html>

只有五张图片,却使用7张来轮播,这是为了实现无缝轮播,后面会详细介绍。

而5个span,即我们可以实时看到轮播图目前所处的位置。

最后是两个按钮,可以通过它来控制前进与后退。

这里我们需要对wrap使用绝对定位,所以用left:-600px;将第一张图片显示出来。

步骤二: css布局

首先,resetcss,如下所示:

* {
	margin: 0;
	padding: 0;
}
a {
	text-decoration: none;
}

接着,我们为了让图片只在container中,所以需要限定其宽度和高度并且使用overflow:hidden;将其余的图片隐藏起来,并且我们希望wrap相对于container左右移动,所以设置为relative,如下:

.container {
	position: relative;
	width: 600px;
	height: 400px;
	margin: 100px auto 0 auto;
	box-shadow: 0 0 5px green;
	overflow: hidden;
}

我们设置wrap是绝对定位的,所以,我们就可以通过控制Left和Right来控制图片的移动了。设置z-index:1;以对后面将要放置的buttons作为参考。 因为共有七张图片,所以width为4200px(每张图片我们设置为600X400),我们只需让图片左浮动即可实现占满一排了。

.wrap {
	position: absolute;
	width: 4200px;
	height: 400px;
	z-index: 1;
}

然后我们把图片设置位左浮动,并限定其大小,如下所示:

.container .wrap img {
	float: left;
	width: 600px;
	height: 400px;
}

现在的效果如下:

即这时已经显示出了第一张图片。并且充满了整个container(container是有box-shadow的);

然后我们把显示次序的buttons放在图片的右下角。并且设置z-index:2;以保证buttons是在图片的上面的。

.container .buttons {
	position: absolute;
	right: 150px;
	bottom: 20px;
	width: 100px;
	height: 10px;
	z-index: 2;
}

然后将buttons下面的span做一个简单的修饰,并且给和图片对应的span设置一个on类,如下:

.container .buttons span {
	margin-left: 5px;
	display: inline-block;
	width: 20px;
	height: 20px;
	border-radius: 50%;
	background-color: green;
	text-align: center;
	color: white;
	cursor: pointer;
}
.container .buttons span.on {
	background-color: red;
}

接下来,我们把左右切换的箭头加上,然后做简单的修饰,注意:因为这里使用实体来表示左右箭头,所以设置font-size才能改变其大小,

.container .arrow {
	position: absolute;
	top: 35%;
	color: green;
	padding: 0px 14px;
	border-radius: 50%;
	font-size: 50px;
	z-index: 2;
	display: none;
}

.container .arrow_left {
	left: 10px;
}

.container .arrow_right {
	right: 10px;
}

.container:hover .arrow {
	display: block;
}

.container .arrow:hover {
	background-color: rgba(0,0,0,0.2);
}

步骤三:添加js逻辑

我们首先获取到 wrap(因为要设置其left才能控制轮播图),然后获取到左右两个箭头,并实现手动轮播,如下:

var wrap = document.querySelector(".wrap");
var next = document.querySelector(".arrow_right");
var prev = document.querySelector(".arrow_left");
next.onclick = function () {
  next_pic();
};
prev.onclick = function () {
  prev_pic();
};
function next_pic() {
  var newLeft = parseInt(wrap.style.left) - 600;
  wrap.style.left = newLeft + "px";
}
function prev_pic() {
  var newLeft = parseInt(wrap.style.left) + 600;
  wrap.style.left = newLeft + "px";
}

值得注意的是,这里wrap.style.left是一个字符串,所以要转化为数字才能进行计算,而设定left时就要加上px成为一个字符串了。

现在我们来测试一下:

可以看到,在第一页时,left值为-600,所以我们可以点击一次上一张,但是当再点击一次时,就出现了空白。同样的,下一张点击,到-3600是最后一张,就不能再继续点击了。

  

也就是说,当我们点击下一张到-3600px(这是第一张图片)时,我们需要下次跳转到第二张,即-1200px;这样才能正常跳转;

同理,当我们点击上一张到0px(这是第五张图片时),我们希望下次跳转到第四张,即-2400px;

按照这样的思路我们重新将next_pic和prev_pic函数修改如下:

function next_pic() {
  var newLeft;
  if (wrap.style.left === "-3600px") {
    newLeft = -1200;
  } else {
    newLeft = parseInt(wrap.style.left) - 600;
  }
  wrap.style.left = newLeft + "px";
}
function prev_pic() {
  var newLeft;
  if (wrap.style.left === "0px") {
    newLeft = -2400;
  } else {
    newLeft = parseInt(wrap.style.left) + 600;
  }
  wrap.style.left = newLeft + "px";
}

这时,我们就可以发现图片可以循环播放了!

但是,这时我们仅仅时手动循环播放的,我们如果希望自动播放,使用setInterval()即可,如下所示:

var timer = null;
function autoPlay() {
  timer = setInterval(function () {
    next_pic();
  }, 1000);
}
autoPlay();

即先设定一个计时器,然后创建一个可以自动播放的函数,最后调用这个函数即可。 现在它就可以自动播放了,效果如下:

但是如果我们想要仔细看其中一个图片的时候,我们希望轮播图停止播放,只要clearInterval()即可,如下:

var container = document.querySelector(".container");
container.onmouseenter = function () {
  clearInterval(timer);
};
container.onmouseleave = function () {
  autoPlay();
};

现在,只要我们把鼠标移入轮播图中,这时轮播图就不会播放了。而移开鼠标之后,轮播图自动播放。

但是到目前为止,轮播图下方的小圆点还没有动,现在我们就实现它。

原理很简单,即设置buttons的index初始值为0,即第一个span的class为on,然后触发next_pic函数时,index加1,当触发prev_pic函数时,inex减1, 并设置当前index的小圆点的class为on, 这就要求index必须设置为全局变量,才能保证它在每一个函数的作用域中。

添加showCurrentDot函数:

var index = 0;
var dots = document.getElementsByTagName("span");
function showCurrentDot() {
  for (var i = 0, len = dots.length; i < len; i++) {
    dots[i].className = "";
  }
  dots[index].className = "on";
}

在next_pic中添加代码:

index++;
if (index > 4) {
  index = 0;
}

在prev_pic中添加大吗:

index--;
if (index < 0) {
  index = 4;
}
showCurrentDot();

这样,轮播图就可以自动切换,并且小圆点也在随着图片的变化而变化了。

但是,这距离我们经常看到的轮播图还有一定距离 - - - 当点击小圆点时, 就可跳转到相应图片。 实现原理即: 点击小圆点,就使wrap的Left变成相应的值。代码如下:

for (var i = 0, len = dots.length; i < len; i++) {
  (function (i) {
    dots[i].onclick = function () {
      var dis = index - i;
      if (index == 4 && parseInt(wrap.style.left) !== -3000) {
        dis = dis - 5;
      }
      //和使用prev和next相同,在最开始的照片5和最终的照片1在使用时会出现问题,导致符号和位数的出错,做相应地处理即可
      if (index == 0 && parseInt(wrap.style.left) !== -600) {
        dis = 5 + dis;
      }
      wrap.style.left = parseInt(wrap.style.left) + dis * 600 + "px";
      index = i;
      showCurrentDot();
    };
  })(i);
}

原理就是当点击到小圆点时,得到相应的i值,这个i值也就是span的index值,我们拿他和全局变量index作比较,然后重新设置wrap.style.left的值,然后把i值复制给全局变量index,最后显示当前的小原点即可。值得注意的是:这里涉及到了闭包的概念,如果直接使用for循环,则不能得到正确的结果。

最终效果如图:

最终代码如下所示:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>轮播图</title>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      a {
        text-decoration: none;
      }
      .container {
        position: relative;
        width: 600px;
        height: 400px;
        margin: 100px auto 0 auto;
        box-shadow: 0 0 5px green;
        overflow: hidden;
      }
      .container .wrap {
        position: absolute;
        width: 4200px;
        height: 400px;
        z-index: 1;
      }
      .container .wrap img {
        float: left;
        width: 600px;
        height: 400px;
      }
      .container .buttons {
        position: absolute;
        right: 5px;
        bottom: 40px;
        width: 150px;
        height: 10px;
        z-index: 2;
      }
      .container .buttons span {
        margin-left: 5px;
        display: inline-block;
        width: 20px;
        height: 20px;
        border-radius: 50%;
        background-color: green;
        text-align: center;
        color: white;
        cursor: pointer;
      }
      .container .buttons span.on {
        background-color: red;
      }
      .container .arrow {
        position: absolute;
        top: 35%;
        color: green;
        padding: 0px 14px;
        border-radius: 50%;
        font-size: 50px;
        z-index: 2;
        display: none;
      }
      .container .arrow_left {
        left: 10px;
      }
      .container .arrow_right {
        right: 10px;
      }
      .container:hover .arrow {
        display: block;
      }
      .container .arrow:hover {
        background-color: rgba(0, 0, 0, 0.2);
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="wrap" style="left: -600px">
        <img src="./img/5.jpg" alt="" />
        <img src="./img/1.jpg" alt="" />
        <img src="./img/2.jpg" alt="" />
        <img src="./img/3.jpg" alt="" />
        <img src="./img/4.jpg" alt="" />
        <img src="./img/5.jpg" alt="" />
        <img src="./img/1.jpg" alt="" />
      </div>
      <div class="buttons">
        <span class="on">1</span>
        <span>2</span>
        <span>3</span>
        <span>4</span>
        <span>5</span>
      </div>
      <a href="javascript:;" class="arrow arrow_left"><</a>
      <a href="javascript:;" class="arrow arrow_right">></a>
    </div>
    <script>
      var wrap = document.querySelector(".wrap");
      var next = document.querySelector(".arrow_right");
      var prev = document.querySelector(".arrow_left");
      next.onclick = function () {
        next_pic();
      };
      prev.onclick = function () {
        prev_pic();
      };
      function next_pic() {
        index++;
        if (index > 4) {
          index = 0;
        }
        showCurrentDot();
        var newLeft;
        if (wrap.style.left === "-3600px") {
          newLeft = -1200;
        } else {
          newLeft = parseInt(wrap.style.left) - 600;
        }
        wrap.style.left = newLeft + "px";
      }
      function prev_pic() {
        index--;
        if (index < 0) {
          index = 4;
        }
        showCurrentDot();
        var newLeft;
        if (wrap.style.left === "0px") {
          newLeft = -2400;
        } else {
          newLeft = parseInt(wrap.style.left) + 600;
        }
        wrap.style.left = newLeft + "px";
      }
      var timer = null;
      function autoPlay() {
        timer = setInterval(function () {
          next_pic();
        }, 2000);
      }
      autoPlay();

      var container = document.querySelector(".container");
      container.onmouseenter = function () {
        clearInterval(timer);
      };
      container.onmouseleave = function () {
        autoPlay();
      };

      var index = 0;
      var dots = document.getElementsByTagName("span");
      function showCurrentDot() {
        for (var i = 0, len = dots.length; i < len; i++) {
          dots[i].className = "";
        }
        dots[index].className = "on";
      }

      for (var i = 0, len = dots.length; i < len; i++) {
        (function (i) {
          dots[i].onclick = function () {
            var dis = index - i;
            if (index == 4 && parseInt(wrap.style.left) !== -3000) {
              dis = dis - 5;
            }
            //和使用prev和next相同,在最开始的照片5和最终的照片1在使用时会出现问题,导致符号和位数的出错,做相应地处理即可
            if (index == 0 && parseInt(wrap.style.left) !== -600) {
              dis = 5 + dis;
            }
            wrap.style.left = parseInt(wrap.style.left) + dis * 600 + "px";
            index = i;
            showCurrentDot();
          };
        })(i);
      }
    </script>
  </body>
</html>

总结:

实现一个轮播图还是不难的,大体思路: 先创建一个div,限定其宽度和高度,overflow:hidden,且设置其position为relative。然后创建一个装图片的div,宽度为所有图片的总宽度,且设置其position为absolute,并且使其中的内容浮动,这样所有的图片就处于一行中。然后为了实现无缝滚动,所以需要在首尾分别添加一张过渡图片。 先添加两个按钮, 使其可以手动轮播,然后只需要添加一个定时器使其朝一个方向自动轮播即可,因为用户有时需要查看详情,所以当鼠标进入时就clear定时器,滑出再定时播放。为了更好地用户体验,我们再下面添加了一排小圆点,用户可以清楚地知道现在所处的位置, 最后, 利用闭包使得用户可以直接通过点击小圆点切换图片。

标签: #轮播图 #JavaScript
推荐文章
HTML5 Canvas是一种强大的Web技术,它允许我们使用JavaScript在网页上创建和...
在这个程序中,我们将使用JavaScript创建一个可以在屏幕上放烟花的效果。我...
轮播图在网站中几乎无处不在,占用地方少,交互性好。今天就来聊聊如何用vu...
大部分网站或APP的首页差不多都运用到了轮播图,下边就探讨一下关于轮播图的...
轮播图实现思路:1、img_ul类里面存放img标签,将需要展示的图片依次排开,在...
推荐专题
如何自己建网站?建网站难不难?其实建网站说难不难,说容易也并不容易,难...
本专题精心收集整理了多种HTML+CSS+JS轮播图实现方案,带详细代码和讲解,正...