JS+JQuery实现无缝连接轮播图


Posted in jQuery onDecember 30, 2020

我之前写过一个简易版的自动+手动轮播图:简易轮播图
但是这个轮播图在切换的时候是没有实现无缝滚动的,每张图片都是单张切换的,而不是滑动。现在用JQuery实现无缝连接的轮播图。

无缝连接的轮播图的原理如下:

JS+JQuery实现无缝连接轮播图

代码:

<!DOCTYPE html>
<html>

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

  #container {
    position: relative;
    /*轮播图容器的宽高*/
    width: 500px;
    height: 260px;
    margin: 20px auto;
    overflow: hidden;
    /*溢出隐藏:只显示一张图片*/
  }

  #container .wrapper {
    position: absolute;
    top: 0;
    left: 0;
    /*每张图片的宽度和轮播图容器的宽度相等,
    整个图片层长度:500*5=2500,由于克隆了一张,多加一张宽度*/
    width: 3000px;
    height: 100%;
  }

  #container .wrapper li {
    width: 500px;
    height: 100%;
    float: left;
  }

  #container .wrapper li img {
    width: 100%;
    height: 100%;
    vertical-align: middle;
    /*去掉未浮动时图片间的上下空隙*/
  }

  #container .btnLeft,
  #container .btnRight {
    display: none;
    z-index: 999;
    width: 30px;
    height: 30px;
    position: absolute;
    top: 50%;
    margin-top: -15px;
    background-color: #9E9E9E;
    border-radius: 20%;
    opacity: 60%;
    font-size: 20px;
    color: #673ab7;
    text-align: center;
    line-height: 30px;
  }

  #container .btnLeft {
    left: 0;
  }

  #container .btnRight {
    right: 0;
  }

  #container .btnLeft:hover,
  #container .btnRight:hover {
    opacity: 70%;
    cursor: pointer;
  }

  /* 鼠标滑过图片的时候显示按钮 */
  #container:hover .btnLeft,
  #container:hover .btnRight {
    display: block;
  }

  /*圆点层*/
  #container .dots {
    background: rgba(0, 0, 0, .3);
    position: absolute;
    left: 50%;
    bottom: 10px;
    transform: translateX(-50%);
    z-index: 999;
    padding: 4px;
    border-radius: 24px;
  }

  #container .dots li {
    width: 15px;
    height: 15px;
    border-radius: 50%;
    background-color: #9e9e9e;
    float: left;
    /*可以使用行块盒*/
    /*display: inline-block;*/
    margin: 0 5px;
    cursor: pointer;
  }

  #container .dots li.active {
    background-color: #c74b42;
  }

  .clearfix::after {
    content: "";
    display: block;
    clear: both;
  }
</style>

<body>
  <!-- 实现轮播图的容器 -->
  <div id="container">
    <!-- 存放全部图片的容器 -->
    <div class="wrapper">
      <!-- LI: 每张图片 -->
      <li><img src="0.jpg"></li>
      <li><img src="1.jpg"></li>
      <li><img src="2.jpg"></li>
      <li><img src="3.jpg"></li>
      <li><img src="4.jpg"></li>
      <!-- 克隆到末尾 -->
      <li><img src="0.jpg"></li>
    </div>

    <div class="btnLeft"><</div>
    <div class="btnRight">></div>
    <!-- 分页器:圆点 -->
    <div class="dots">
      <ul class="clearfix">
        <li class="active"></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
      </ul>
    </div>
  </div>
  <script src="jquery-1.11.3.min.js"></script>
  <!-- <script src="index.js"></script> -->
  <script type="text/javascript">

    let $container = $('#container'),
      $wrapper = $container.children('.wrapper'),
      $btnLeft = $container.find('.btnLeft'),
      $btnRight = $container.find('.btnRight'),
      $dots = $container.find('.dots'),
      $dotList = $dots.find('li');

    let autoTimer = null,
      interval = 2000,
      imgIndex = 0; //当前轮播的图片索引,默认第一张
    // 自动轮播
    function autoPlay() {
      // 让wrapper向左移动
      imgIndex++;
      /* if(imgIndex === 4) imgIndex = 0; 这样写会导致图片会一下变到第一张,不是无缝滚动
      无缝滚动:
      1. 把第一张克隆一份放到末尾,wrapper中会比真实的图片层多一张
      2. 依然一张张往后滚动,滚动到第5张的时候,继续向后走(imgIndex=6),看到了克隆的第一张,再要向后走的时候,
        让其“立即”跳转到真实的第一张(肉眼看不出跳转),然后运动到第二张......
      */
      if (imgIndex > 5) {
        // 上次显示的是克隆的那张,忽略真实的第一张,让其立即跳转到第二张
        $wrapper.css('left', 0);
        imgIndex = 1;
      }

      // 匀速向左移动
      // 无动画版:$wrapper.css('transform', 'translate(' + (-imgIndex * 500) + 'px)');
      // 动画版:
      $wrapper.stop().animate({
        left: -imgIndex * 500 //JQ自动补'px'
      }, 300);

      showDots();
    }
    autoTimer = setInterval(autoPlay, interval);

    // 圆点对焦
    function showDots() {
      // 由于不能修改imgIndex的值,所以定义一个临时变量
      let temp = imgIndex;
      temp === 5 ? temp = 0 : null;
      $dotList.each((index, item) => {
        let $item = $(item);
        if (index === temp) {
          $item.addClass('active');
          return;
        }
        $item.removeClass('active');
      });
    }

    // 鼠标进入/离开轮播区域时停止/开启自动轮播
    $container.on('mouseenter', () => {
      clearInterval(autoTimer);
    });

    $container.on('mouseleave', () => {
      autoTimer = setInterval(autoPlay, interval);
    });

    // 点击圆点
    $dotList.click(function () {
      let index = $(this).index();
      imgIndex = index;

      $wrapper.stop().animate({
        left: -imgIndex * 500 //JQ自动补'px'
      }, 300);

      showDots();
    });

    // 左键点击
    $btnLeft.click(function () {
      imgIndex--;
      if (imgIndex < 0) {
        // 上次显示的是真实的第一张,忽略克隆的倒数第一张,让其立即跳转倒数第二张
        $wrapper.css('left', -2500);
        imgIndex = 4;
      }

      $wrapper.stop().animate({
        left: -imgIndex * 500 //JQ自动补'px'
      }, 300);

      showDots();
    });

    // 右键点击:相当于自动轮播
    $btnRight.click(function() {
      autoPlay();
    });

  </script>

</body>

</html>

这段代码用单例模式优化一下:

html部分:test.html

<!DOCTYPE html>
<html>

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

  #container {
    position: relative;
    /*轮播图容器的宽高*/
    width: 500px;
    height: 260px;
    margin: 20px auto;
    overflow: hidden;
    /*溢出隐藏:只显示一张图片*/
  }

  #container .wrapper {
    position: absolute;
    top: 0;
    left: 0;
    /*每张图片的宽度和轮播图容器的宽度相等,
    整个图片层长度:500*5=2500,由于克隆了一张,多加一张宽度*/
    width: 3000px;
    height: 100%;
  }

  #container .wrapper li {
    width: 500px;
    height: 100%;
    float: left;
  }

  #container .wrapper li img {
    width: 100%;
    height: 100%;
    vertical-align: middle;
    /*去掉未浮动时图片间的上下空隙*/
  }

  #container .btnLeft,
  #container .btnRight {
    display: none;
    z-index: 999;
    width: 30px;
    height: 30px;
    position: absolute;
    top: 50%;
    margin-top: -15px;
    background-color: #9E9E9E;
    border-radius: 20%;
    opacity: 60%;
    font-size: 20px;
    color: #673ab7;
    text-align: center;
    line-height: 30px;
  }

  #container .btnLeft {
    left: 0;
  }

  #container .btnRight {
    right: 0;
  }

  #container .btnLeft:hover,
  #container .btnRight:hover {
    opacity: 70%;
    cursor: pointer;
  }

  /* 鼠标滑过图片的时候显示按钮 */
  #container:hover .btnLeft,
  #container:hover .btnRight {
    display: block;
  }

  /*圆点层*/
  #container .dots {
    background: rgba(0, 0, 0, .3);
    position: absolute;
    left: 50%;
    bottom: 10px;
    transform: translateX(-50%);
    z-index: 999;
    padding: 4px;
    border-radius: 24px;
  }

  #container .dots li {
    width: 15px;
    height: 15px;
    border-radius: 50%;
    background-color: #9e9e9e;
    float: left;
    /*可以使用行块盒*/
    /*display: inline-block;*/
    margin: 0 5px;
    cursor: pointer;
  }

  #container .dots li.active {
    background-color: #c74b42;
  }

  .clearfix::after {
    content: "";
    display: block;
    clear: both;
  }
</style>

<body>
  <!-- 实现轮播图的容器 -->
  <div id="container">
    <!-- 存放全部图片的容器 -->
    <div class="wrapper">
      <!-- LI: 每张图片 -->
      <li><img src="0.jpg"></li>
      <li><img src="1.jpg"></li>
      <li><img src="2.jpg"></li>
      <li><img src="3.jpg"></li>
      <li><img src="4.jpg"></li>
      <!-- 克隆到末尾 -->
      <li><img src="0.jpg"></li>
    </div>

    <div class="btnLeft"><</div>
    <div class="btnRight">></div>
    <!-- 分页器:圆点 -->
    <div class="dots">
      <ul class="clearfix">
        <li class="active"></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
      </ul>
    </div>
  </div>
  <script src="jquery-1.11.3.min.js"></script>
  <script src="index.js"></script>

</body>

</html>

JS部分:index.js

function debounce(func, wait, immediate) {
  let timer = null,
    result = null;
  return function anonymous(...args) {
    let context = this,
      now = immediate && !timer;
    clearTimeout(timer);
    timer = setTimeout(() => {
      timer = null;
      !immediate ? (result = func.call(context, ...args)) : null;
    }, wait);
    now ? (result = func.call(context, ...args)) : null;
    return result;
  };
}

let bannerModule = (function () {
  let $container = $("#container"),
    $wrapper = $container.children(".wrapper"),
    $btnLeft = $container.find(".btnLeft"),
    $btnRight = $container.find(".btnRight"),
    $dots = $container.find(".dots"),
    $dotList = $dots.find("li");

  let autoTimer = null,
    interval = 2000,
    imgIndex = 0; //当前轮播的图片索引,默认第一张
  // 自动轮播
  function autoPlay() {
    // 让wrapper向左移动
    imgIndex++;
    /* if(imgIndex === 4) imgIndex = 0; 这样写会导致图片会一下变到第一张,不是无缝滚动
        无缝滚动:
        1. 把第一张克隆一份放到末尾,wrapper中会比真实的图片层多一张
        2. 依然一张张往后滚动,滚动到第5张的时候,继续向后走(imgIndex=6),看到了克隆的第一张,再要向后走的时候,
          让其“立即”跳转到真实的第一张(肉眼看不出跳转),然后运动到第二张......
        */
    if (imgIndex > 5) {
      // 上次显示的是克隆的那张,忽略真实的第一张,让其立即跳转到第二张
      $wrapper.css("left", 0);
      imgIndex = 1;
    }

    // 匀速向左移动
    // 无动画版:$wrapper.css('transform', 'translate(' + (-imgIndex * 500) + 'px)');
    // 动画版:
    $wrapper.stop().animate({
      left: -imgIndex * 500 //JQ自动补'px'
    }, 300);

    showDots();
  }

  // 圆点对焦
  function showDots() {
    // 由于不能修改imgIndex的值,所以定义一个临时变量
    let temp = imgIndex;
    temp === 5 ? (temp = 0) : null;
    $dotList.each((index, item) => {
      let $item = $(item);
      if (index === temp) {
        $item.addClass("active");
        return;
      }
      $item.removeClass("active");
    });
  }

  //点击圆点
  function clickDots() {
    $dotList.click(debounce(function () {
      let index = $(this).index();
      imgIndex = index;

      $wrapper.stop().animate({
        left: -imgIndex * 500 //JQ自动补'px'
      }, 300);

      showDots();
    },300,true));
  }

  // 左右按键
  function btnClick() {
    $btnLeft.click(function () {
      imgIndex--;
      if (imgIndex < 0) {
        // 上次显示的是真实的第一张,忽略克隆的倒数第一张,让其立即跳转倒数第二张
        $wrapper.css('left', -2500);
        imgIndex = 4;
      }

      $wrapper.stop().animate({
        left: -imgIndex * 500 //JQ自动补'px'
      }, 300);

      showDots();
    });

    // 右键点击:相当于自动轮播
    $btnRight.click(debounce(autoPlay, 300, true));
  }

  return {
    init: function () {
      autoTimer = setInterval(autoPlay, interval);

      // 鼠标进入/离开轮播区域时停止/开启自动轮播
      $container.on("mouseenter", () => {
        clearInterval(autoTimer);
      });
      $container.on("mouseleave", () => {
        autoTimer = setInterval(autoPlay, interval);
      });

      clickDots();
      btnClick();
    },
  };
})();

bannerModule.init();

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

jQuery 相关文章推荐
jQuery插件FusionWidgets实现的Bulb图效果示例【附demo源码下载】
Mar 23 jQuery
jQuery EasyUI 组件加上“清除”功能实例详解
Apr 11 jQuery
node.js+jQuery实现用户登录注册AJAX交互
Apr 28 jQuery
jQuery实现的简单在线计算器功能
May 11 jQuery
深入理解jquery的$.extend()、$.fn和$.fn.extend()
Jul 08 jQuery
jQuery获取table表中的td标签(实例讲解)
Jul 28 jQuery
jQuery Datatables表头不对齐的解决办法
Nov 27 jQuery
jquery+css3实现熊猫tv导航代码分享
Feb 12 jQuery
jquery.param()实现数组或对象的序列化方法
Oct 08 jQuery
jQuery pagination分页示例详解
Oct 23 jQuery
Jquery使用each函数实现遍历及数组处理
Jul 14 jQuery
jQuery实现容器间的元素拖拽功能
Dec 01 jQuery
JS实现选项卡插件的两种写法(jQuery和class)
Dec 30 #jQuery
jQuery实现简单轮播图效果
Dec 27 #jQuery
原生jQuery实现只显示年份下拉框
Dec 24 #jQuery
jquery实现鼠标悬浮弹出气泡提示框
Dec 23 #jQuery
jquery实现图片放大镜效果
Dec 23 #jQuery
jQuery实现增删改查
Dec 22 #jQuery
jQuery实现本地存储
Dec 22 #jQuery
You might like
功能齐全的PHP发送邮件类代码附详细说明
2008/07/10 PHP
几种有用的变型 PHP中循环语句的用法介绍
2012/01/30 PHP
php实现utf-8和GB2312编码相互转换函数代码
2013/02/07 PHP
php5.5新数组函数array_column使用
2013/07/08 PHP
PHP使用CURL获取302跳转后的地址实例
2014/05/04 PHP
PHP实现对站点内容外部链接的过滤方法
2014/09/10 PHP
php5.2的curl-bug 服务器被php进程卡死问题排查
2016/09/19 PHP
基于JQuery框架的AJAX实例代码
2009/11/03 Javascript
读jQuery之六 缓存数据功能介绍
2011/06/21 Javascript
Jquery easyui 下loaing效果示例代码
2013/08/12 Javascript
轻松创建nodejs服务器(2):nodejs服务器的构成分析
2014/12/18 NodeJs
探讨JavaScript语句的执行过程
2016/01/28 Javascript
底部悬浮通栏可以关闭广告位的实现方法
2016/06/01 Javascript
15款最好的Bootstrap在线编辑器
2016/08/03 Javascript
利用jQuery插件imgAreaSelect实现图片上传裁剪(同步显示图像位置信息)
2016/12/02 Javascript
JS 调用微信扫一扫功能
2016/12/22 Javascript
JavaScript中附件预览功能实现详解(推荐)
2017/08/15 Javascript
vue登录注册及token验证实现代码
2017/12/14 Javascript
Bootstrap popover 实现鼠标移入移除显示隐藏功能方法
2018/01/24 Javascript
vue中锚点的三种方法
2018/07/06 Javascript
使用electron将vue-cli项目打包成exe的方法
2018/09/29 Javascript
jQuery实现移动端下拉展现新的内容回弹动画
2020/06/24 jQuery
python定时复制远程文件夹中所有文件
2019/04/30 Python
Python Pandas实现数据分组求平均值并填充nan的示例
2019/07/04 Python
python opencv捕获摄像头并显示内容的实现
2019/07/11 Python
Python监控服务器实用工具psutil使用解析
2019/12/19 Python
解决tensorflow添加ptb库的问题
2020/02/10 Python
Pycharm 如何一键加引号的方法步骤
2021/02/05 Python
HTML5中的nav标签学习笔记
2016/06/24 HTML / CSS
HTML5在canvas中绘制复杂形状附效果截图
2014/06/23 HTML / CSS
AmazeUI的JS表单验证框架实战示例分享
2020/08/21 HTML / CSS
国际性能运动服装品牌:Dare 2b
2018/07/27 全球购物
EJB包括(SessionBean,EntityBean)说出他们的生命周期,及如何管理事务的?
2013/02/17 面试题
项目合作计划书
2014/01/09 职场文书
2014幼儿园中班工作总结
2014/11/10 职场文书
《游戏王:大师决斗》将推出新卡牌包4月4日上线
2022/03/31 其他游戏