原生js实现轮播图的示例代码


Posted in Javascript onFebruary 20, 2017

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

原理:

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

步骤一:建立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"><</a>
    <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="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;
    }

现在的效果如下:

原生js实现轮播图的示例代码    

即这时已经显示出了第一张图片。并且充满了整个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成为一个字符串了。

现在我们来测试一下:

原生js实现轮播图的示例代码 

可以看到,在第一页时,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();

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

原生js实现轮播图的示例代码

但是如果我们想要仔细看其中一个图片的时候,我们希望轮播图停止播放,只要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循环,则不能得到正确的结果。

最终效果如图:

原生js实现轮播图的示例代码  

最终代码如下所示:

<!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"><</a>
    <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" 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。然后创建一个装图片的div,宽度为所有图片的总宽度,并且使其浮动,这样所有的图片就处于一行中。然后为了实现无缝滚动,所以需要在首尾分别添加一张过渡图片。 先添加两个按钮, 使其可以手动轮播,然后只需要添加一个定时器使其朝一个方向自动轮播即可,因为用户有时需要查看详情,所以当鼠标进入时就clear定时器,滑出再定时播放。为了更好地用户体验,我们再下面添加了一排小圆点,用户可以清楚地知道现在所处的位置, 最后, 利用闭包使得用户可以直接通过点击小圆点切换图片。

Javascript 相关文章推荐
JS模拟面向对象全解(二、类型与赋值)
Jul 13 Javascript
自动最大化窗口的Javascript代码
May 22 Javascript
js实现二代身份证号码验证详解
Nov 20 Javascript
JavaScript的事件代理和委托实例分析
Mar 25 Javascript
教你JS中的运算符乘方、开方及变量格式转换
Aug 09 Javascript
javascript实现一个网页加载进度loading
Jan 04 Javascript
详解Angular Reactive Form 表单验证
Jul 06 Javascript
用JS实现简单的登录验证功能
Jul 28 Javascript
jQuery取得元素标签名称小结(附代码)
Aug 16 jQuery
jQuery简单判断值是否存在于数组中的方法示例
Apr 17 jQuery
vue动态注册组件实例代码详解
May 30 Javascript
浅谈Vue2.4.0 $attrs与inheritAttrs的具体使用
Mar 08 Javascript
深入理解Javascript中的观察者模式
Feb 20 #Javascript
浅谈js中function的参数默认值
Feb 20 #Javascript
angularJS+requireJS实现controller及directive的按需加载示例
Feb 20 #Javascript
浅谈js函数三种定义方式 &amp; 四种调用方式 &amp; 调用顺序
Feb 19 #Javascript
js 输入框 正则表达式(菜鸟必看教程)
Feb 19 #Javascript
js通过keyCode值判断单击键盘上某个键,然后触发指定的事件方法
Feb 19 #Javascript
基于Angular.js实现的触摸滑动动画实例代码
Feb 19 #Javascript
You might like
PHP 5昨天隆重推出--PHP 5/Zend Engine 2.0新特性
2006/10/09 PHP
从Web查询数据库之PHP与MySQL篇
2009/09/25 PHP
PHP防止图片盗用(盗链)的方法小结
2016/11/11 PHP
JavaScript中两个感叹号的作用说明
2011/12/28 Javascript
js实现拉伸拖动iframe的具体代码
2013/08/03 Javascript
jquery easyui combobox模糊过滤(示例代码)
2013/11/30 Javascript
jQuery中操控hidden、disable等无值属性的方法
2014/01/06 Javascript
js unicode 编码解析关于数据转换为中文的两种方法
2014/04/21 Javascript
JS实现常见的TAB、弹出层效果(TAB标签,斑马线,遮罩层等)
2015/10/08 Javascript
整理Javascript基础入门学习笔记
2015/11/29 Javascript
jqueryMobile使用示例分享
2016/01/12 Javascript
jQuery实现图像旋转动画效果
2016/05/29 Javascript
深入理解JavaScript内置函数
2016/06/03 Javascript
微信公众号-获取用户信息(网页授权获取)实现步骤
2016/10/21 Javascript
详谈js中window.location.search的用法和作用
2017/02/13 Javascript
jquery处理checkbox(复选框)是否被选中实例代码
2017/06/12 jQuery
详谈Node.js之操作文件系统
2017/08/29 Javascript
jQuery简单实现对数组去重及排序操作实例
2017/10/31 jQuery
Vue实现动态创建和删除数据的方法
2018/03/17 Javascript
JavaScript如何获取一个元素的样式信息
2019/07/29 Javascript
判断“命令按钮”是否被鼠标单击详解
2019/07/31 Javascript
微信小程序使用Vant Weapp组件库的方法步骤
2019/08/01 Javascript
Vue中的循环及修改差值表达式的方法
2019/08/29 Javascript
python实现人脸识别经典算法(一) 特征脸法
2018/03/13 Python
python让列表倒序输出的实例
2018/06/25 Python
Python笔试面试题小结
2019/09/07 Python
用Python解数独的方法示例
2019/10/24 Python
浅谈python opencv对图像颜色通道进行加减操作溢出
2020/06/03 Python
广州迈达威.net面试题目
2012/03/10 面试题
汽车检测与维修应届毕业生求职信
2013/10/19 职场文书
银行柜员应聘推荐信范文
2013/11/24 职场文书
九年级历史教学反思
2014/01/27 职场文书
社区禁毒工作方案
2014/06/02 职场文书
个园导游词
2015/02/04 职场文书
详解Java ES多节点任务的高效分发与收集实现
2021/06/30 Java/Android
详解Vue的列表渲染
2021/11/20 Vue.js