开发一款高复用的前端轮播图插件

1.需求:

     目前项目中很多页面都用到了轮播图,虽然轮播图的展现形式不一样,但是我们可以把轮播图的共性给抽象出来,开发出一款插件,让使用到轮播图的页面都引用这个插件.当前这款插件是使用jquery开发的,兼容IE8.

2.结果图:

2.具体实现

   2.1 js文件

(function(){

    function Carousel(options){

       this.dom = (options.dom instanceof $)?options.dom:$(options.dom);
       this.hasDots =  options.hasDots || false;//轮播图是否包含指示器
       this.duration = options.duration || 5000;//自动轮播的时间
       this.autoScroll = options.autoScroll || false; //是否开启自动轮播呢
       this.index = 0;//当前的索引
       this.hasLeftAndRight = options.hasLeftAndRight || false; //是否有左右点击框
       this.scrollSpeed = options.scrollSpeed || 250;//轮播滑动切换的时间
       this.leftAndRightCallback = options.leftAndRightCallback || function(){};//当含有左右点击按钮时的回调函数
       if(window.getComputedStyle){//计算轮播图每一项的宽度,下面的写法是兼容ie8
        this.item_width = parseInt(getComputedStyle(this.dom.find(".item-hook")[0]).width);
       }else{
        this.item_width = parseInt(this.dom.find(".item-hook")[0].currentStyle.width);   
       }
       this.count = this.dom.find(".item-hook").length;//计算轮播图的数量
       this.init();

    }

    /**
     * 初始化
     */
    Carousel.prototype.init = function(){
       if(this.autoScroll){ //轮播图是否自动轮播
        this.setLoop();
        this.bindEvent();
       } 
       this.setDots();
       this.updateLeftAndRight(0);
       this.bindLeftAndRightEvent();
    }

    /**
     * 左右事件的绑定
     */
    Carousel.prototype.bindLeftAndRightEvent = function(){

        var _this = this;

       this.dom.find(".left-hook").on("click",function(){
           
          _this.updateView(_this.index-1);
          _this.updateLeftAndRight(_this.index-1);

       })

       this.dom.find(".right-hook").on("click",function(){

         _this.updateView(_this.index+1);
         _this.updateLeftAndRight(_this.index+1);
           
       })

    }


    /**
     * 更新左右框的状态
     */
    Carousel.prototype.updateLeftAndRight = function(index){

        if(!this.hasLeftAndRight){
          return false;
        }

        this.index = index;

        if(this.index == 0){
            this.dom.find(".left-hook").hide();
            this.dom.find(".right-hook").show();
        }else if(this.index == this.count-1){
            this.dom.find(".left-hook").show();
            this.dom.find(".right-hook").hide();
        }else{
            this.dom.find(".left-hook").show();
            this.dom.find(".right-hook").show();
        }
        
        this.leftAndRightCallback(this.index);

    }

    /**
     * 设置轮播图的小点点
     * 
     * 根据轮播图上面的有几个元素就生成几个指示器,并且给指示器绑定点击事件
     * 
     */
    Carousel.prototype.setDots = function(){
        if(!this.hasDots){
          return false;
        }

        var list = this.dom.find(".dots-hook");

        var itemHtml  =$("<div></div>").append($(list.find(".dots-item-hook").removeClass("current").get(0)).clone()).html();

        var length = this.dom.find(".item-hook").length;

        if(length<=1){
            list.hide();
            return false;
        }

        var dots_content="";

        for(var i = 0;i<length;i++){
            dots_content+=itemHtml;
        }

        list.html(dots_content);

        $(list.find(".dots-item-hook").get(0)).addClass("current");

        var _this =this;
        
        list.on("click",function(e){
          
           var target = e.target || window.srcElement;

           if(!$(target).hasClass("dots-item-hook")){
               return false;
           }

           var index = $(target).index();

           _this.updateView(index);

        })

    }
     
    /**
     * 渲染轮播图
     * 
     * 通过获取到的索引值触发轮播图滚动到指定索引的位置
     * 
     * 
     */
    Carousel.prototype.updateView = function(index){

        if(this.index == index){
          return false;
        }

        var list = this.dom.find(".list-hook");

        var symbol = this.index -index;

        var _this = this;

        if(symbol>0){ //点击小圆点向右滚

            var arr = Array.prototype.slice.call(list.find(".item-hook"),0);

            var dom_item = arr.splice(arr.length-this.index,this.index);

            arr = dom_item.concat(arr);

            list.append(arr);

            list.css("left",-1*this.index*this.item_width);

            list.animate({
                left:-1*index*this.item_width
            },this.scrollSpeed,function(){

                _this.afterScrollHandler(index,index);

            })


        }else{ //向左滚

            list.animate({
                left:symbol*this.item_width
            },this.scrollSpeed,function(){

               _this.afterScrollHandler(index,Math.abs(symbol));
                
    
            })

        }
    }

    /**
     * 轮播图滚动后后处理
     */
    
    Carousel.prototype.afterScrollHandler = function(index,num){

        var list = this.dom.find(".list-hook");

        this.index = index;

        var arr = Array.prototype.slice.call(list.find(".item-hook"),0);

        var del_datas = arr.splice(0,num);

        arr = arr.concat(del_datas);

        list.append(arr);

        list.css("left",0);

        this.updateDots();

    }

    /**
     * 渲染小红点
     */
    Carousel.prototype.updateDots = function(){

        var list = this.dom.find(".dots-hook");
        list.find(".dots-item-hook").removeClass("current");
        $(list.find(".dots-item-hook")[this.index]).addClass("current");  

    }
    
    /**
     * 设置定时器循环播放
     * 
     * 每过5s就改变一次外部容器div的left的值,让其产生向左滑动的效果,滑动完毕
     * 后将轮播图的第一个元素提出来塞到队伍的最后一个,并将外部容器left的值恢复为0
     */
    Carousel.prototype.setLoop = function(){

        var _this = this;

        this.timer = setInterval(function(){

          var list = _this.dom.find(".list-hook");

          list.animate({
           left:-1*_this.item_width+"px"
          },250,function(){
            _this.index++;
            if(_this.index>=_this.count){
                _this.index = 0;
            }
            _this.updateDots();
            $(list.find(".item-hook")[0]).appendTo(list);
            list.css("left",0);
          })

        },_this.duration)

    }
    
    /**
     * 绑定鼠标触摸事件
     * 
     * 定义鼠标划入和划出的两个事件,滑入时让轮播图暂停自动轮播,划出时恢复自动轮播
     * 
     */
    Carousel.prototype.bindEvent =  function(){

        var list = this.dom.find(".list-hook");

        var _this = this;

        this.dom.on("mouseenter",function(){
            clearInterval(_this.timer);
            _this.timer = null;
        })

        this.dom.on("mouseleave",function(){

            _this.timer = setInterval(function(){
      
                list.animate({
                 left:-1*_this.item_width+"px"
                },250,function(){
                  _this.index++;
                  if(_this.index>=_this.count){
                      _this.index = 0;
                  }
                  _this.updateDots();
                  $(list.find(".item-hook")[0]).appendTo(list);
                  list.css("left",0);
                })
      
              },_this.duration)

        })

    }


    window.Carousel = Carousel;

  }  
)();

2.2 html形式

 <!--banner轮播图-->
 <div class="banner-carousel" id="carousel">


        <div class="list list-hook">
                <div class="item item-hook"><img src="../img/static/banner1.png" /></div>
                <div class="item item-hook"><img src="../img/static/banner2.png" /></div>
                <div class="item item-hook"><img src="../img/static/banner3.png" /></div>
       </div>     

           
        <ul class="dots-hook">
               <li class="dots-item-hook current"></li>
               <li class="dots-item-hook"></li>
               <li class="dots-item-hook"></li>
        </ul>

    
  </div>

说明:html的内容可以多样化,但有几个类名必须要加上.轮播图列表包裹容器需要添加一个类名list-hook,每个轮播的对象要添加类名item-hook.如果需要使用到指示器,指示器的包裹容器需要添加上类名dots-hook,里面的单项需要添加上类名dots-item-hook.如果使用到了左右标识点击滑动,那么html上面相应的地方要加上类名,左标识加left-hook,右标识为right-hook.

2.3 css形式

具体的样式可以自由发挥,但有几点必须注意:

       1.list-hook的父元素要设置position:relative和overflow:hidden

       2.list-hook必须和父元素完全重合(宽高设置为100%即可),定位方式改为绝对定位,而且不能让子元素换行.这个地方注意一下,

       list-hook的宽度并不等于几个item-hook的宽度和,而是list-hook的宽度=list-hook父元素宽度=每个item-hook的宽度 . 

       3.子元素设置为行内块元素,横向拍成一列

.banner-carousel {
    width: 100%;
    height: 452px;
    position: relative;
    overflow: hidden;
}
.list-hook{
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    white-space: nowrap;
    font-size: 0;
}
.item-hook{
    width: 100%;
    height: 100%;
    display: inline-block;
}

3.具体使用

 把页面的上的dom对象传进去,其次可以根据需求传递相应的参数

  //初始化banner轮播图  
  new Carousel({
      dom:$("#carousel"),
      hasDots:true,  //使用指示器
      autoScroll:true //开启自动轮播
  });

分析:

此轮播图最复杂的一块是js文件中的updateView方法.具体实现细节如下:

首先将当前的索引值和需要滚动的索引值相减得到symbol值,根据symbol值的正负可以轻易的知道当前轮播图需要向左滚动还是向右滚动.

如果是向左滚动很好处理,向左滑动若干个宽度,将滑动到左侧的几个元素提出来塞到队伍的后面去

向右滑动就有些麻烦了,首先要想办法把轮播图恢复到最初的那个顺序才能向左滑动.比如原来的轮播图顺序是1234,经过3轮自动轮播变成了4123.我现在点击1的指示器,想让第四个轮播图向左滑动到第一个,那该如何处理呢?先要想办法将4123恢复到1234才能向左滑动,只需要将4后面的123截下来提到4的前面去.arr.length-this.index就是需要截取的起始位置,截取下来后塞到队伍的前面去,就能恢复到最初的位置.在这里我们没有一个一个去改变dom元素的位置,而是先把dom元素的类数组对象转化成普通数组,在普通数组中调整好顺序,父元素再append该普通数组,就能立刻将页面上dom元素的顺序进行调整.

发布了20 篇原创文章 · 获赞 4 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/brokenkay/article/details/101284508