原生JavaScript实现无缝轮播图完整教程

作者:拾光

时间:2026-10-21

浏览:128

本文详细讲解如何使用原生JavaScript从零构建一个支持无缝滚动、自动播放及手动控制的轮播图组件。内容涵盖HTML结构搭建、CSS样式布局、JS核心逻辑(含无缝跳转算法、定时器控制及闭包应用),并提供完整代码示例,帮助开发者掌握前端动态交互技巧。

文章目录

原生JavaScript实现无缝轮播图完整教程

许多网站都配备了轮播图功能,但缺乏系统性的讲解资料。本文旨在提供一份简明教程,帮助读者掌握其实现原理。若文中存在疏漏或错误,欢迎指正。

轮播图核心原理

核心原理:

将多张图片在同一行内水平排列,通过计算偏移量并结合定时器,实现图片的定时自动轮播效果。

HTML结构搭建

第一步:构建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:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="arrow_left">&lt;</a>
    <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="arrow_right">&gt;</a>
  </div>
</body>
</html>

虽然实际只有五张图片,但为了支持无缝滚动效果,我们在列表首尾各添加了一张过渡图片,使总数达到七张。这一设计将在后续部分详细阐述。

此外,页面中包含五个span元素,用于实时显示当前轮播图所处的位置索引。

最后,左右两侧各有一个按钮,用于用户手动控制图片的前进与后退切换。

在CSS中,我们需要对容器wrap应用绝对定位,并设置left:-600px;,以确保初始状态下第一张图片正确显示。

CSS样式布局

第二步:CSS样式布局

首先引入resetcss进行基础样式重置,代码如下:


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

接着,为确保图片仅显示在container容器范围内,需设定其宽高并设置overflow:hidden;以隐藏溢出内容。同时,将wrap设置为relative定位,使其能够相对于container进行左右移动,具体样式如下:


   .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;以便后续放置的按钮位于图片上层。因共有七张图片,每张图片尺寸为600x400像素,故wrap总宽度设为4200px。只需让图片左浮动即可实现单行排列。


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

随后,将图片设置为左浮动并限定大小,效果如下:


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

此时的页面效果如下:

原生JavaScript实现无缝轮播图完整教程    

此时第一张图片已显示,并充满整个container(container带有box-shadow边框阴影效果)。

接下来,将显示当前序号的按钮放置在图片右下角,并设置z-index:2;以确保按钮层级高于图片。


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

对按钮下方的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);
    }

JavaScript交互逻辑实现

第三步:添加JavaScript交互逻辑

首先获取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单位并转为字符串。

现在进行测试:

原生JavaScript实现无缝轮播图完整教程 

从效果可见,当处于第一页时,left值为-600。此时点击一次“上一张”按钮,若再点击则会出现空白区域。同样,点击“下一张”至-3600px(即最后一张可见图)后,无法继续点击。

这意味着,当点击“下一张”到达-3600px(实际显示的是第一张图片)时,下一次操作应直接跳转至第二张图片,即left值变为-1200px,从而实现无缝衔接。

同理,当点击“上一张”到达0px(实际显示的是第五张图片)时,下一次操作应跳转至第四张图片,即left值变为-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();

即先定义一个计时器,创建自动播放函数,并调用该函数。现在轮播图已具备自动播放功能,效果如下:

原生JavaScript实现无缝轮播图完整教程  

若用户希望仔细查看某张图片,可暂停自动播放。只需调用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函数时,index减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();

至此,轮播图已能自动切换,且小圆点指示器随图片变化同步更新。

但距离常见的高级轮播图仍有差距——当点击小圆点时,应直接跳转至对应图片。实现原理为:点击小圆点时,获取对应的i值(即span的index值),与全局变量index比较,重新设置wrap.style.left的值,将i值赋给全局变量index,最后显示当前小圆点。代码如下:

 


 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值(即span的index值),将其与全局变量index比较,重新设置wrap.style.left的值,将i值赋给全局变量index,最后显示当前小圆点。值得注意的是:此处涉及闭包概念,若直接使用for循环,将无法得到正确结果。

最终效果如图所示:

原生JavaScript实现无缝轮播图完整教程  

完整代码如下所示:


<!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:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="arrow arrow_left">&lt;</a>
    <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="arrow arrow_right">&gt;</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;。接着创建包含图片的div,宽度设为所有图片总宽,并使其浮动,从而使所有图片处于同一行。为实现无缝滚动,需在首尾各添加一张过渡图片。先添加两个按钮以实现手动轮播,再添加定时器实现单向自动播放。考虑到用户可能需要查看详情,当鼠标移入时清除定时器,移出时恢复定时播放。为提升用户体验,底部添加一排小圆点,清晰指示当前位置。最后,利用闭包技术,使用户可通过点击小圆点直接切换图片。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章