原生JavaScript实现焦点轮播图

通过学习,我理解了图片轮播原理,学习了setTimeout()、setInterval()函数设置定时器与清除定时器clearInterval()函数,使用函数递归实现图片滑动切换,采用辅助图片实现图片无限滚动等编程技巧。

一、焦点图轮播特效之原理

这个焦点图轮播特效将运用到了平时学习中的知识,例如,DOM操作、定时器、事件处理、JS动画、函数递归还有无线滚动等等。
其实焦点图轮播特效的原理十分简单,就是通过控制存放图片的列表里面的left值来显示图片。
HTML结构大致分为以下部分:

<div id="container">
       <div id="list" style="left:-600px;">
         ![](img\5.jpg)
         ![](img\1.jpg)
         ![](img\2.jpg)
         ![](img\3.jpg)
         ![](img\4.jpg)
         ![](img\5.jpg)
         ![](img\1.jpg)
       </div>
       <div id="buttons">
         <span index="1" class="on"></span>
         <span index="2"></span>
         <span index="3"></span>
         <span index="4"></span>
         <span index="5"></span>
       </div>
       <a href="javascript:;" id="prev" class="arrow"><</a><!--javascript:是一个伪协议,是表示在触发<a>默认动作时,执行一段javascript代码,而javascript:;表示什么都不执行,这样点击<a>标签没有任何反应-->
       <a href="javascript:;" id="next" class="arrow">></a>
    </div>
  • 一个父容器container,父容器里面有一个图片列表list还有一个按钮buttons,再加上两个代表左右箭头的a标签;
  • javascript: 是一个伪协议,是是表示在触发a标签默认动作时,执行一段javascript代码,而javascript:;表示什么都不执行,这样点击a标签没有任何反应;
  • 为了实现无限滚动,在第一张图片之前加入第五张图片的附属图,在第五张图片之后加入第一张图片的附属图,实得在滚动的过程中,不会出现延迟现象;
二、焦点图轮播特效之样式布局

具体的CSS代码如下:

<style>
      *{
        margin:0;
        padding:0;
        text-decoration:none;
      }
      body{
        padding:20px;
      }
      #container{
        width:600px;
        height:400px;
        border:3px solid #333;
        overflow:hidden;
        position:relative;
      }
      #list{
        width:4200px;
        height:400px;
        position:absolute;
        z-index:1;
      }
      #list img{
        float:left;
      }
      #buttons{
        position:absolute;
        height:10px;
        width:100px;
        bottom:20px;
        left:250px;
        z-index:2;
      }
      #buttons span{
        cursor:pointer;
        float:left;
        border:1px solid #fff;
        width:10px;
        height:10px;
        border-radius:50%;
        background:#333;
        margin-right:5px;
      }
      #buttons .on{
        background:orangered;
      }
      .arrow{
        cursor:pointer;
        display:none;
        line-height:39px;
        text-align:center;
        font-size:36px;
        font-weight:bold;
        width:40px;
        height:40px;
        position:absolute;
        z-index:2;
        top:180px;
        background-color:RGBA(0,0,0,.3);
        color:#fff;
      }
      .arrow:hover{
        background-color:RGBA(0,0,0,.7);
      }
      #container:hover .arrow{
        display:block;
      }
      #prev{
        left:20px;
      }
      #next{
        right:20px;
      }
    </style>
  • 其中将父容器里面的overflow属性设置为:hidden,并且将position设置为:relative,因为子元素list和buttons都是相对于父容器来定位的;
  • 其中里面涉及到了z-index属性:设置元素的堆叠顺序。元素可拥有负的z-index属性值,z-index仅仅能在定位元素上奏效,拥有更高层叠顺序的元素总是位于更低元素的前面;
三、焦点图轮播特效之箭头切换

接下来就进入JS部分的编写,首先必须是页面加载完毕才能执行相关的JS代码,所以必须写在window.onload = function(){}中,接下来先取得相关的容器和标签,如下:

window.onload = function(){
var container = document.getElementById("container");
var list = document.getElementById("list");
var buttons = document.getElementById("buttons").getElementsByTagName("span");
var prev = document.getElementById("prev");
var next = document.getElementById("next");
}

然后要做到点击箭头就能切换,就必须给箭头元素绑定一个点击事件,通过点击箭头,来改变list里面style属性中的left值,从而实现图片的切换

prev.onclick = function(){
      list.style.left = parseInt(list.style.left) - 600 + 'px';
}
next.onclick = function(){
     list.style.left = parseInt(list.style.left) + 600 + 'px';
}

因为两个点击事件里面的语句十分相似,所以就将它们封装在一个名为animate()的函数中,只需要传进一个偏移量就可以了,如下

 function animate(offset) {
     list.style.left = parseInt(list.style.left) + offset + 'px';
}
prev.onclick = function(){
      animate(-600);
}
next.onclick = function(){
     animate(600);
}
四、焦点图轮播特效之无限滚动

在上一节,我们已经实现了箭头的切换,但是会有一个问题,当切换到最左边,或者最右边时,会出现空白页,因为当滚动到第五张图片的附属图时,此时的left值为0,当继续往左切换时,就会大于0,当滚动到第一张图片的附属图时,此时的left值为-4200,当继续往右切换时,就会小于-4200,所以会出现空白现象;我们要达到的效果是,当滚动到第一张图片的附属图时,此时将它的left值设置回-600,当滚动到第五张图片的附属图时,将left值设置回-3000,才能达到无限滚动的效果,具体代码如下:

function animate(offset) {
     var newLeft = parseInt(list.style.left) + offset;
     list.style.left = newLeft + 'px';
     if(newLeft > -600) {
          list.style.left = -3000 + 'px';
    }
    if(newLeft < -3000) {
          list.style.left = -600 + 'px';
    }
}

此时就可以实现无限滚动的效果了,这个时候,我们还需要加上小圆点的切换功能,这时候我们需要再引进一个变量index,来显示当前显示的是第几张图片,初始值为1;并且增加一个函数专门来亮起小圆点,如下:

function showButtons(){
       buttons[index-1].className = "on";
}

每点击一下左箭头,index的值就要减1,每点击一下右箭头,index的值就加1,如下:

prev.onclick = function(){
      index -= 1;
      showButtons();
      animate(-600);
}
next.onclick = function(){
     index += 1;
     showButtons();
     animate(600);
}

但是这个时候会发现,以前的按钮没有关闭,而是全都亮了起来,此时就要改进一下showButtons()函数,在亮起当前按钮的同时,将之前的按钮至灰色,代码如下:

function showButtons(){
       for(var i = 0; i < buttons.length; i++) {
             if(buttons[i].className == "on") {
                  buttons[i].className  = "";
                  break;
             }
      }
       buttons[index-1].className = "on";
}

还需要对index的值进行限制,不能让它无限的减下去,或者加上去,修改后的代码如下:

prev.onclick = function(){
      if(index == 5) {
          index = 1;
      } else {
        index -= 1;
    }
       showButtons();
       animate(-600);
}
next.onclick = function(){
     if(index == 1) {
        index = 5;
     } else {
        index += 1;
    }
    showButtons();
    animate(600); 
}
五、焦点图轮播特效之按钮切换

实现完了箭头的切换,接下来就要实现按钮的切换了,就是要分别给buttons数组里面的每个元素添加一个点击事件,跟箭头切换不同的是,按钮切换的偏移量需要计算,有可能跨几幅图片切换,还有,每张图片里面有个index属性,显示自己是第几张图片,如下:

for(var i = 0; i< buttons.length; i++) {
      buttons[i].onclick = function() {
           var myIndex = parseInt(this.getAttribute('index'));
           var offset = -600 * (myIndex - index);
           animate(offset);
           index = myIndex;//更新index值
           showButton();
    }
}
  • 这里面有一个点需要注意,span标签里面index属性是属于自定义属性,不能通过点表示法来取得,所以要使用getAttribute()方法来获取,即能取自定义属性,又能取自身有的属性;

此时还有一些需要优化的地方,当我位于当前图片的时候,再点击当前按钮,后台还会执行,但是我们的理想情况应该是,位于当前图片的时候,再点击当前按钮,就应该不做任何事情,加一个判断语句,优化后的代码如下:

for(var i = 0; i< buttons.length; i++) {
      buttons[i].onclick = function() {
           if(this.className == 'on') {
               return;
          }
           var myIndex = parseInt(this.getAttribute('index'));
           var offset = -600 * (myIndex - index);
           animate(offset);
           index = myIndex;//更新index值
           showButton();
    }
}
六、焦点轮播图之动画函数

在进行图片的切换过程中,图片是缓慢的移动切换的,而不是一张图片一张图片的切换过去,这不是我们想要的效果,这里就涉及到了javascript中的动画效果和函数;
它的原理是在切换的过程中,不断地进行一小段的位移,直到达到目标值,清楚了原理,接下来就来写代码:
我们增加了位移总时间的变量、位移间隔还有计算出每次的位移量,并且定义了一个位移函数go(),当每次的位移量小于0并且left大于新的left目标值时,还有一种情况是,每次的位移量大于0并且left小于新的left目标值时,left值就等于left加上每次的位移量,然后调用setTimeout函数不断地递归调用,直到达到目标值;

 function animate(offset){
            animated = true;
            var newLeft = parseInt(list.style.left) + offset;
            var time = 300;//位移总时间
            var interval = 10; //位移间隔
            var speed = offset/(time/interval);//每次位移量
            function go(){
                if ((speed < 0 && parseInt(list.style.left) > newLeft) || (speemd >0 && parseInt(list.style.left) < newLeft)) {
                    list.style.left = parseInt(list.style.left) + speed + 'px';
                    setTimeout(go,interval);
                }
                else{
                   animated = false;
                   list.style.left = newLeft + 'px';
                   if(newLeft > -600){
                      list.style.left = -3000 + 'px';
                   }
                   if(newLeft < -3000){
                      list.style.left = -600 + 'px';
                   }
               }
            }
            go();
           }
  • 这里要注意的是,setTimeout()方法接受两个参数,一个执行的函数代码,一个间隔,函数会在这个间隔后执行一次,不会重复执行,但是因为调用的是自身,所以相当于递归不断地重复执行;
七、焦点图轮播特效之自动播放

我们会注意到,当我们把鼠标移出图片列表时,图片会自动切换,当把鼠标移进去时,就会停止自动切换,这里,我们就需要引入两个函数:play()还有stop()函数,并且为container父容器添加两个事件:onmouseover还有onmouseout,具体的代码如下:

       function play(){
            timer = setInterval(function(){
                    next.onclick();
                },1500);
           }
      function stop(){
      clearInterval(timer);
      }
      container.onmouseover = stop;
      container.onmouseout = play;
      play();

还重新定义了一个时间变量timer,并且执行setInterval方法,经过间隔时间不断地执行函数代码,然后停止函数里面,就清楚调这个时间变量timer;

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容

  • 原理 图片轮播原理:将一系列大小相等的图片平铺,利用css布局只显示一张图片,其他图片隐藏,通过计算偏移量利用定时...
    黎贝卡beka阅读 2,204评论 1 2
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,943评论 4 60
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,049评论 25 707
  • 不知道从什么时候开始刷微博,刷朋友圈,甚至是刷新闻,成了下意识的行为。 尤其是自己发了一条动态之后的刷,会更加频繁...
    狂想而已阅读 296评论 0 2
  • 如果这生命中有一段旅程,总要错过后才完整,谁不曾怀疑过,相信过,等待过,离开过。我只想说经历过就值得。 关于你...
    苏沐晴阅读 356评论 0 5