原生JS实现无缝轮播

大兔子大兔子 提交于 2019-12-21 10:16:52

今天分享前端开发学习中的一个很经典的案例——原生JS实现无缝轮播图。

需求:

1.鼠标移入轮播图时左右两边显示上一页下一页按钮,移出时隐藏

2.鼠标点击箭头,图片发生轮播

3.点击号码,切换到指定图片

4.鼠标移出,图片每隔一定时间自动轮播

5.当图片轮播到最后或最前一张的时候,图片无缝循环切换

HTML页面结构:这里把图片换成背景颜色了,使用时直接添加图片路径即可

 <div class="all" id='box'>
    <div class="screen">
        <ul>
            <li><img src="../2019-12-11js/img/1.jpg" width="500" height="300" /></li>
            <li><img src="../2019-12-11js/img/2.jpg" width="500" height="300"/></li>
            <li><img src="../2019-12-11js/img/3.jpg" width="500" height="300" /></li>
            <li><img src="../2019-12-11js/img/4.jpg" width="500" height="300" /></li>
            <li><img src="../2019-12-20动画js/0.jpg" width="500" height="300" /></li>
            <li><img src="../2019-12-11js/img/1.jpg" width="500" height="300" /></li>
           </ul>
           <ol>
               <li class="current">1</li>
               <li>2</li>
               <li>3</li>
               <li>4</li>
               <li>5</li>
           </ol>
   
       </div>
       <div id="arr"><span id="left">&lt;</span><span id="right">&gt;</span></div>
   </div>

CSS样式:样式部分比较简单,重点让li标签浮动并排,然后在盒子(类名为screen的div)里显示其中一张,其他的隐藏(overflow:hidden),整个轮播思想就是移动整个ul标签。

 <style>
          * {
        padding: 0;
        margin: 0;
        list-style: none;
        border: 0;
    }

    .all {
        width: 500px;
        height: 300px;
        padding: 7px;
        border: 1px solid #ccc;
        margin: 100px auto;
        position: relative;
    }

    .screen {
        width: 500px;
        height: 300px;
        overflow: hidden;
        position: relative;
    }

    .screen li {
        width: 500px;
        height: 300px;
        overflow: hidden;
        float: left;
    }

    .screen ul {
        position: absolute;
        left: 0;
        top: 0px;
        width: 3000px;
    }

    .all ol {
        position: absolute;
        right: 10px;
        bottom: 10px;
        line-height: 20px;
        text-align: center;
    }

    .all ol li {
        float: left;
        width: 20px;
        height: 20px;
        background: #fff;
        border: 1px solid #ccc;
        margin-left: 10px;
        cursor: pointer;
        border-radius: 50%;

    }

    .all ol li.current {
        background: yellow;
    }

    #arr {
        display: none;
    }

    #arr span {
        width: 40px;
        height: 40px;
        position: absolute;
        left: 5px;
        top: 50%;
        margin-top: -20px;
        background: #000;
        cursor: pointer;
        line-height: 40px;
        text-align: center;
        font-weight: bold;
        font-family: '黑体';
        font-size: 30px;
        color: #fff;
        opacity: 0.3;
        border: 1px solid #fff;
    }

    #arr #right {
        right: 5px;
        left: auto;
    }
</style>

JS处理:

第一步:完成轮播图事件的添加 :用一个全局变量index记录当前需要展示的图片的索引

(1)鼠标移入移出事件:鼠标移入,显示左右切换按钮,移出时隐藏

(2)上一页下一页按钮点击事件点击下一页:index++,点击上一页:index–

(3)页码点击事件:切换指定图片

第二步:完成上一页和下一页

(1)点击移动之前给ul添加边界检测:否则点击下一页会无限往右滚动

(2)修改当前索引(自增/自减),索引表示的是当前ul应该展示第几张图片

(3)移动ul(目标距离 = -index * screen的宽度)

(4)页码保持同步(当前显示的是第几张图片,下方页码对应索引高亮)

第三步:完成无限轮播 核心思想:n+1

(1)常规思路:图片滚动时,当滚动到最后一张时,我们偷偷的快速改变ul的位置到第一张(不要动画,瞬间改变)

ul.style.left = ‘0px’; //ul回到初始位置

index = 0; //index恢复到0

(2)问题发现:这种方式可以实现无限轮播,但是在下一轮无限的时候第一张会被跳过去

原因:我们手动改变了index为0,而动画又需要index+1,所以会错过index为0的那一张

(3)解决方案:我们在最后一张图片的后面加上第一张图片(第6张)可以让用户看到滚动效果,然后滚动到第六张时,再改变ul回到初始位置

好处:①用户可以看到滚动效果,不影响体验; ②刚好第6张与第一张是同一张图片,快速改变位置不会造成动画的闪现

(4)当图片index为最后一张的的时候,页码应该显示第一个,因为最后一张和第一张是同一张图片

第四步:完成点击页码跳转

(1)点击的是第几个页码,移动动画的目标距离 = -index * screen.offsetWidth

(2)排他思想改变页码样式

(3)页码的下标需要与图片下标index保持一致,否则会产生冲突,即点击页码的时候,要让图片下标index与页码下标一致

第五步:自动无限轮播

相当于每隔一段时间自动点击下一页按钮,代码逻辑完全不变

(1)将轮播代码封装成一个函数

(2)开启定时器,每隔一段时间执行这个函数

(3)鼠标移入时清除定时器,移出时开启定时器

<script>
// 1.获取页面对应的元素
var box=document.getElementById("box"); //最外部大盒子
var arr=document.getElementById("arr");
var screen=document.getElementsByClassName("screen")[0]; //轮播图显示区域div
var ul=document.getElementsByTagName("ul")[0]; //显示图片的ul
var ol=document.getElementsByTagName("ol")[0]; //显示页码的ol
var left=document.getElementById("left"); //上一张箭头
var right=document.getElementById("right"); //下一张箭头
   var index=0; ////声明一个变量记录图片的索引,默认第0张图片

   //2.给box添加鼠标移入和移出事件
   //2.1 鼠标移入
   box.onmouseover= function () {
       arr.style.display="block"; //显示上一页下一页箭头
       clearInterval(timeId); //清除定时器(即鼠标移入时,图片要停止自动轮播)
   };
   //2.2 鼠标移出
   box.onmouseout= function () {
       arr.style.display="none"; //隐藏箭头
       timeId=setInterval(scroll,2000);  //重启定时器(鼠标移出,图片要恢复自动轮播)
   };

   //3.给上一页下一页箭头添加点击事件
   //3.1 下一页,图片向左轮播
   right.onclick= function () {
       scroll(); 
   };
   //3.2 上一页,图片向右轮播
   left.onclick= function () { 
       //(1)边界检测,如果当前已经是第一张,则不做任何处理
       if(index==0){   
           //无限轮播原理:如果当前是第一张,则偷偷修改ul的位置是最后一张(第一张与最后一张是同一张图片)
           index=ul.children.length-1; //index恢复到最后一张
           ul.style.left=-index*screen.offsetWidth+"px"; ////ul回到最后一张位置
       }
       //(2)索引自减
       index--;
        // (3)向左移动ul:目标距离 = -screen的宽度 * 索引
       animationMove(ul,-index*screen.offsetWidth,10);
       indexShow(); //同步页码样式
   };

   //4.给页码添加点击事件
   for(var i=0;i<ol.children.length;i++){
        //4.1 循环遍历数组时给每一个页码添加一个liIndex属性记录下标
       ol.children[i].liIndex=i;
       ol.children[i].onclick= function () {
           index=this.liIndex-1;
           scroll();
       };
   }

   var timeId=setInterval(scroll,2000);
   // 封装一个向右轮播的函数
   function scroll(){
       //(1)边界检测:如果当前已经是最后一张(第n+1张,n代表需要轮播的图片数量)
       if(index==ul.children.length-1){
           //无限轮播的原理就是滚动到最后一张的时候,偷偷快速的改变ul的位置到第一张(不要任何动画,一瞬间改变)            
           index=0; //index恢复到0
           ul.style.left=0+"px"; //ul回到初始位置
       } 
       // (2)索引自增
       index++; 
       // (3)向右移动ul:目标距离 = -screen的宽度 * 索引
       animationMove(ul,-index*screen.offsetWidth,10);
       indexShow(); //同步页码样式
   }
   //5.页码样式保持同步:排他思想(当前页码添加样式,其他页码移除该样式)
   function indexShow(){
       for(var i=0;i<ol.children.length;i++){
           if(i==index){
               ol.children[i].classList.add("current");
           }else{
               ol.children[i].classList.remove("current"); 
           }
           //特殊情况:当index为最后一张的时候,页码应该显示第一张
           if(index==ul.children.length-1){
               ol.children[0].classList.add("current");
           }
       }
   }
   // 封装一个滚动动画函数
   function animationMove(obj,target,speed){
       clearInterval(obj.timeId);  //每次执行动画先清除原有的定时器
       obj.timeId=setInterval(function () {
           var currentLeft=obj.offsetLeft; //获取当前位置
          var isLeft=currentLeft>target?true:false;   //是否往左走
          if(isLeft){
              currentLeft-=10;    //往左走
          }else{
              currentLeft+=10;    //往右走
          }
          if(isLeft?currentLeft>target:currentLeft<target){
             obj.style.left=currentLeft+"px";  //如果当前位置不是在目标位置则进行位置处理
          }else{
              clearInterval(obj.timeId);
              obj.style.left=target+"px";
          }
          // if(currentLeft>target){
          //     currentLeft-=10;
          //     obj.style.left=currentLeft+"px";
          // }else if(currentLeft<target){
          //     currentLeft+=10;
          //     obj.style.left=currentLeft+"px";
          // }else{
          //     clearInterval(obj.timeId);
          //     obj.style.left=target+"px";
          // }
      },speed);
  }
 </script>

在这里插入图片描述
条件有限 发不了动图哈哈

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!