• 原生JS实现无缝轮播


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

    需求:

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

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

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

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

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

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

     1 <div class="all" id='box'>
     2     <div class="screen">
     3         <ul>
     4             <li><img src="" width="500" height="200" style="background-color: yellowgreen;"/></li>
     5             <li><img src="" width="500" height="200" style="background-color: pink;"/></li>
     6             <li><img src="" width="500" height="200" style="background-color: skyblue;"/></li>
     7             <li><img src="" width="500" height="200" style="background-color: greenyellow;"/></li>
     8             <li><img src="" width="500" height="200" style="background-color: plum;"/></li>
     9             <li><img src="" width="500" height="200" style="background-color: orange;"/></li>
    10         </ul>
    11         <ol>
    12             <li class="current">1</li>
    13             <li>2</li>
    14             <li>3</li>
    15             <li>4</li>
    16             <li>5</li>
    17         </ol>
    18 
    19     </div>
    20     <div id="arr"><span id="left">&lt;</span><span id="right">&gt;</span></div>
    21 </div>

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

     1 <style type="text/css">
     2         * {
     3             padding: 0;
     4             margin: 0;
     5             list-style: none;
     6             border: 0;
     7         }
     8 
     9         .all {
    10             width: 500px;
    11             height: 200px;
    12             padding: 7px;
    13             border: 1px solid #ccc;
    14             margin: 100px auto;
    15             position: relative;
    16         }
    17 
    18         .screen {
    19             width: 500px;
    20             height: 200px;
    21             overflow: hidden;
    22             position: relative;
    23         }
    24 
    25         .screen li {
    26             width: 500px;
    27             height: 200px;
    28             overflow: hidden;
    29             float: left;
    30         }
    31 
    32         .screen ul {
    33             position: absolute;
    34             left: 0;
    35             top: 0px;
    36             width: 3000px;
    37         }
    38 
    39         .all ol {
    40             position: absolute;
    41             right: 10px;
    42             bottom: 10px;
    43             line-height: 20px;
    44             text-align: center;
    45         }
    46 
    47         .all ol li {
    48             float: left;
    49             width: 20px;
    50             height: 20px;
    51             background: #fff;
    52             border: 1px solid #ccc;
    53             margin-left: 10px;
    54             cursor: pointer;
    55         }
    56 
    57         .all ol li.current {
    58             background: yellow;
    59         }
    60 
    61         #arr {
    62             display: none;
    63         }
    64 
    65         #arr span {
    66             width: 40px;
    67             height: 40px;
    68             position: absolute;
    69             left: 5px;
    70             top: 50%;
    71             margin-top: -20px;
    72             background: #000;
    73             cursor: pointer;
    74             line-height: 40px;
    75             text-align: center;
    76             font-weight: bold;
    77             font-family: '黑体';
    78             font-size: 30px;
    79             color: #fff;
    80             opacity: 0.3;
    81             border: 1px solid #fff;
    82         }
    83 
    84         #arr #right {
    85             right: 5px;
    86             left: auto;
    87         }
    88     </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)鼠标移入时清除定时器,移出时开启定时器

      1 <script>
      2     // 1.获取页面对应的元素
      3     var box=document.getElementById("box"); //最外部大盒子
      4     var arr=document.getElementById("arr");
      5     var screen=document.getElementsByClassName("screen")[0]; //轮播图显示区域div
      6     var ul=document.getElementsByTagName("ul")[0]; //显示图片的ul
      7     var ol=document.getElementsByTagName("ol")[0]; //显示页码的ol
      8     var left=document.getElementById("left"); //上一张箭头
      9     var right=document.getElementById("right"); //下一张箭头
     10     var index=0; ////声明一个变量记录图片的索引,默认第0张图片
     11 
     12     //2.给box添加鼠标移入和移出事件
     13     //2.1 鼠标移入
     14     box.onmouseover= function () {
     15         arr.style.display="block"; //显示上一页下一页箭头
     16         clearInterval(timeId); //清除定时器(即鼠标移入时,图片要停止自动轮播)
     17     };
     18     //2.2 鼠标移出
     19     box.onmouseout= function () {
     20         arr.style.display="none"; //隐藏箭头
     21         timeId=setInterval(scroll,2000);  //重启定时器(鼠标移出,图片要恢复自动轮播)
     22     };
     23 
     24     //3.给上一页下一页箭头添加点击事件
     25     //3.1 下一页,图片向左轮播
     26     right.onclick= function () {
     27         scroll(); 
     28     };
     29     //3.2 上一页,图片向右轮播
     30     left.onclick= function () { 
     31         //(1)边界检测,如果当前已经是第一张,则不做任何处理
     32         if(index==0){   
     33             //无限轮播原理:如果当前是第一张,则偷偷修改ul的位置是最后一张(第一张与最后一张是同一张图片)
     34             index=ul.children.length-1; //index恢复到最后一张
     35             ul.style.left=-index*screen.offsetWidth+"px"; ////ul回到最后一张位置
     36         }
     37         //(2)索引自减
     38         index--;
     39          // (3)向左移动ul:目标距离 = -screen的宽度 * 索引
     40         animationMove(ul,-index*screen.offsetWidth,10);
     41         indexShow(); //同步页码样式
     42     };
     43 
     44     //4.给页码添加点击事件
     45     for(var i=0;i<ol.children.length;i++){
     46          //4.1 循环遍历数组时给每一个页码添加一个liIndex属性记录下标
     47         ol.children[i].liIndex=i;
     48         ol.children[i].onclick= function () {
     49             index=this.liIndex-1;
     50             scroll();
     51         };
     52     }
     53 
     54     var timeId=setInterval(scroll,2000);
     55     // 封装一个向右轮播的函数
     56     function scroll(){
     57         //(1)边界检测:如果当前已经是最后一张(第n+1张,n代表需要轮播的图片数量)
     58         if(index==ul.children.length-1){
     59             //无限轮播的原理就是滚动到最后一张的时候,偷偷快速的改变ul的位置到第一张(不要任何动画,一瞬间改变)            
     60             index=0; //index恢复到0
     61             ul.style.left=0+"px"; //ul回到初始位置
     62         } 
     63         // (2)索引自增
     64         index++; 
     65         // (3)向右移动ul:目标距离 = -screen的宽度 * 索引
     66         animationMove(ul,-index*screen.offsetWidth,10);
     67         indexShow(); //同步页码样式
     68     }
     69     //5.页码样式保持同步:排他思想(当前页码添加样式,其他页码移除该样式)
     70     function indexShow(){
     71         for(var i=0;i<ol.children.length;i++){
     72             if(i==index){
     73                 ol.children[i].classList.add("current");
     74             }else{
     75                 ol.children[i].classList.remove("current"); 
     76             }
     77             //特殊情况:当index为最后一张的时候,页码应该显示第一张
     78             if(index==ul.children.length-1){
     79                 ol.children[0].classList.add("current");
     80             }
     81         }
     82     }
     83     // 封装一个滚动动画函数
     84     function animationMove(obj,target,speed){
     85         clearInterval(obj.timeId);  //每次执行动画先清除原有的定时器
     86         obj.timeId=setInterval(function () {
     87             var currentLeft=obj.offsetLeft; //获取当前位置
     88            var isLeft=currentLeft>target?true:false;   //是否往左走
     89            if(isLeft){
     90                currentLeft-=10;    //往左走
     91            }else{
     92                currentLeft+=10;    //往右走
     93            }
     94            if(isLeft?currentLeft>target:currentLeft<target){
     95               obj.style.left=currentLeft+"px";  //如果当前位置不是在目标位置则进行位置处理
     96            }else{
     97                clearInterval(obj.timeId);
     98                obj.style.left=target+"px";
     99            }
    100             // if(currentLeft>target){
    101             //     currentLeft-=10;
    102             //     obj.style.left=currentLeft+"px";
    103             // }else if(currentLeft<target){
    104             //     currentLeft+=10;
    105             //     obj.style.left=currentLeft+"px";
    106             // }else{
    107             //     clearInterval(obj.timeId);
    108             //     obj.style.left=target+"px";
    109             // }
    110         },speed);
    111     }
    112 </script>
  • 相关阅读:
    test
    莫烦Python
    资源汇总
    AutoHotkey学习资源
    神器AutoHotkey学习(官方文档翻译)
    linux内核编译时bad register name `%dil'错误
    Linux内核修炼之道-->原作者博客链接--oschina备份
    vim笔记--oschina备份
    vim相关资源--oschina备份
    Windows下装Gvim时可能发生的错误--oschina备份
  • 原文地址:https://www.cnblogs.com/linqb/p/9375197.html
Copyright © 2020-2023  润新知