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+Ajax+xml实现中国地区选择三级联动菜单效果(推荐)
Jun 09 jQuery
jQuery复合事件用法示例
Jun 10 jQuery
jQuery制作input提示内容(兼容IE8以上)
Jul 05 jQuery
jQuery ajax调用webservice注意事项
Oct 08 jQuery
jQuery实现手机号正则验证输入及自动填充空格功能
Jan 02 jQuery
jQuery与vue实现拖动验证码功能
Jan 30 jQuery
jQuery实现的五星点评功能【案例】
Feb 18 jQuery
jQuery实现动态加载(按需加载)javascript文件的方法分析
May 31 jQuery
js/jQuery实现全选效果
Jun 17 jQuery
JS/jQuery实现超简单的Table表格添加,删除行功能示例
Jul 31 jQuery
jQuery Raty星级评分插件使用方法实例分析
Nov 25 jQuery
jQuery实现的移动端图片缩放功能组件示例
May 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
vBulletin HACK----关于排版的两个HACK
2006/10/09 PHP
PHP通用检测函数集合
2006/11/25 PHP
php执行sql语句的写法
2009/03/10 PHP
php ctype函数中文翻译和示例
2014/03/21 PHP
详解PHP发送邮件知识点
2018/05/06 PHP
jquery 插件 任意位置浮动固定层
2008/12/25 Javascript
JavaScript Event学习第十一章 按键的检测
2010/02/10 Javascript
解读JavaScript代码 var ie = !-[1,] 最短的IE判定代码
2011/05/28 Javascript
javascript解析json数据的3种方式
2014/05/08 Javascript
JS实现向表格中动态添加行的方法
2015/03/30 Javascript
BootStrap使用file-input插件上传图片的方法
2016/09/05 Javascript
jquery利用json实现页面之间传值的实例解析
2016/12/12 Javascript
基于vue的下拉刷新指令和滚动刷新指令
2016/12/23 Javascript
纯javascript前端实现base64图片下载(兼容IE10+)
2018/09/14 Javascript
vue实现表单未编辑或未保存离开弹窗提示功能
2020/04/08 Javascript
vue单元格多列合并的实现
2020/11/26 Vue.js
[46:55]LGD vs Liquid 2019国际邀请赛小组赛 BO2 第一场 8.16
2019/08/19 DOTA
Python Flask基础教程示例代码
2018/02/07 Python
Python实现利用163邮箱远程关电脑脚本
2018/02/22 Python
用Python下载一个网页保存为本地的HTML文件实例
2018/05/21 Python
Python中shapefile转换geojson的示例
2019/01/03 Python
python2.7使用plotly绘制本地散点图和折线图
2019/04/02 Python
ZABBIX3.2使用python脚本实现监控报表的方法
2019/07/02 Python
python等差数列求和公式前 100 项的和实例
2020/02/25 Python
Python利用socket模块开发简单的端口扫描工具的实现
2021/01/27 Python
HTML5的结构和语义(5):交互
2008/10/17 HTML / CSS
html5适合移动应用开发的12大特性
2014/03/19 HTML / CSS
求职者简历中的自我评价
2013/10/20 职场文书
幼儿如何来做好自我评价
2013/11/05 职场文书
中学教师岗位职责
2013/11/26 职场文书
制衣厂各岗位职责
2013/12/02 职场文书
员工培训邀请函
2014/01/11 职场文书
小学数学国培感言
2014/03/10 职场文书
《蝙蝠和雷达》教学反思
2014/04/23 职场文书
研究生导师推荐信
2014/09/06 职场文书
法院执行局工作总结
2015/08/11 职场文书