js轮播图

187 阅读1分钟

//2017-11-02

轮播啦:

function Carousel(options){
    var opts = $.extend({
        node : null,
        direction : 'left',
        wait : 5000,
        time : 500,
        current : 0,
        needPagination : true,
        needQuickButton : true,
        callback : null
    },options);
    this.node = opts.node;
    this.direction = opts.direction;
    this.wait = opts.wait;
    this.time = opts.time;
    this.needPagination = opts.needPagination;
    this.needQuickButton = opts.needQuickButton;
    this.callback = opts.callback;
    //查询属性
    this.content = this.node.find("[data-node='content']");
    this.group = this.content.children();
    this.len = this.group.length;
    this.width = this.node.width();
    this.height = this.node.height();
    this.interval = null;
    this.moveState = false;//移动状态判断
    this.prepStep = 0;//前置累加步长
    this.appStep = 0;//后置累加步长
    //判断默认当前
    this.current = opts.current >= this.len ? 0 : opts.current;
};
Carousel.prototype = {
    constructor:Carousel,
    trigger:function(){
        var _this = this;
        if(!_this.node || !_this.node.length || !_this.content.length){
            if(typeof _this.callback == 'function'){
                _this.callback(0);
            }
            return
        }
        //检测尺寸
        if(_this.getCxtSize() <= _this.width){return}
        //克隆child
        _this.clonePrepFill()
        _this.cloneAppFill();
        //设置content尺寸
        _this.setCxtSize();
        //创建页码
        _this.createPagination();
        //创建滚动盒子
        _this.createScrollBox();
        //创建快捷按钮
        _this.createQuickBtn();
        //绑定事件
        _this.bindEve();
        //定位scroll位置
        _this.setCurScroll();
        //设置当前页码
        _this.setCurPagination();
        //定时器开始
        _this.startInterval();
        //回调
        if(typeof _this.callback == 'function'){
            _this.callback(_this.current + 1);
        }
    },
    //获取content尺寸
    getCxtSize:function(){
        var _this = this;
        //统计每个子集尺寸
        _this.countSize = [];
        //设置子集组
        var children = _this.content.children();
        var size = 0;
        children.each(function(){
            var _size = _this.getDOMSize($(this));
            _this.countSize.push(size);
            size += _size;
        });
        return size;
    },
    //设置content尺寸
    setCxtSize:function(){
        var _this = this;
        var size = _this.getCxtSize();
        var style = {};
        style[_this.direction == 'left' ? 'width' : 'height'] = size + 'px';
        _this.content.css(style);
    },
    //获取dom尺寸
    getDOMSize:function(dom){
        var _this = this;
        return _this.direction == 'left' ? dom.outerWidth(true) : dom.outerHeight(true);
    },
    //克隆前置填充
    clonePrepFill:function(){
        var _this = this;
        var size = 0;
        for(var i = _this.countSize.length - 1; i >= 0; i--){
            //累加尺寸
            size += _this.countSize[i];
            //插入
            _this.content.prepend(_this.group.eq(i).clone(true));
            //累加数量
            _this.prepStep++;
            if(size >= _this.width){
                break;
            }
        }
        
    },
    //克隆后置填充
    cloneAppFill:function(){
        var _this = this;
        var size = 0;
        for(var i = 0; i < _this.countSize.length; i++){
            size += _this.countSize[i];
            //插入
            _this.content.append(_this.group.eq(i).clone(true));
            //累加数量
            _this.appStep++;
            if(size >= _this.width){
                break;
            }
        } 
    },
    //创建滚动盒子
    createScrollBox:function(){
        var _this = this;
         _this.content.wrap("<div data-node='scroll'></div>");
         _this.scroll = _this.node.find("[data-node='scroll']");
         _this.scroll.css({
             width : _this.width + 'px',
            height : _this.height + 'px',
            overflow : 'hidden'
         });
    },
    //创建页码
    createPagination:function(){
        var _this = this;
        //是否需要页码
        if(!_this.needPagination){return}
        var pagination = ["<div class='pagination vo-clear'>"];
        for(var i = 1; i <= _this.len; i++){
            pagination.push("<b>" + i + "</b>");
        }
        pagination.push("</div>");
        _this.node.append(pagination.join(''));
        _this.pagination = _this.node.find('.pagination b');
    },
    //创建快捷按钮
    createQuickBtn:function(){
        var _this = this;
        if(!_this.needQuickButton){return}
        var quickBtn = "<a href='javascript:;' class='next-btn' data-node='next'>&gt;</a><a href='javascript:;' class='prev-btn' data-node='prev'>&lt;</a>";
        _this.node.append(quickBtn);
        _this.nextBtn = _this.node.find("[data-node='next']");
        _this.prevBtn = _this.node.find("[data-node='prev']");
    },
    //获取真是索引
    getRealIndex:function(){
        var _this = this;
        return _this.current + _this.prepStep;
    },
    //设置当前页码
    setCurPagination:function(){
        var _this = this;
        if(!_this.needPagination){return}
        var index = _this.current; 
        index = index >= _this.len ? 0 : index;
        index = index < 0 ? _this.len - 1 : index;
        _this.pagination.eq(index).addClass('on').siblings().removeClass('on');
    },
    //设置当前滚动条
    setCurScroll:function(){
        var _this = this;
        var cur = _this.getRealIndex();
        var size = _this.countSize[cur];
        _this.direction == 'left' ? _this.scroll.scrollLeft(size) : _this.scroll.scrollTop(size);
    },
    //移动
    handleMove:function(){
        var _this = this;
        var cur = _this.getRealIndex();
        var scroll = {};
        scroll[_this.direction == 'left' ? 'scrollLeft' : 'scrollTop'] = _this.countSize[cur];
        _this.moveState = true;
        //设置当前页面
        _this.setCurPagination();
        //动画
        _this.scroll.stop(true).animate(scroll,_this.time,'linear',function(){
            _this.handleReset();
            _this.moveState = false;
            //回调
            if(typeof _this.callback == 'function'){
                _this.callback(_this.current + 1);
            }
        });
    },
    //设置滚动条是否复位
    handleReset : function(){
        var _this = this;
        if(_this.current >= _this.len){
            _this.current = 0;
            _this.setCurScroll();
        }
        if(_this.current < 0){
            _this.current = _this.len - 1;
            _this.setCurScroll();
        }
    },
    //开始
    startInterval:function(){
        var _this = this;
        //停止当前定时器
        _this.stopInterval();
        //开启新定时器
        _this.interval = setInterval(function(){
            _this.current ++;
            _this.handleMove();
        },_this.wait);
    },
    //停止
    stopInterval:function(){
        var _this = this;
        if(_this.interval === null){return}
        clearInterval(_this.interval);
        _this.interval = null;
    },
    //点击页码
    handlePagination:function(){
        var _this = this;
        return function(){
            var index = $(this).index();
            if(_this.moveState || _this.current == index){return false}
            _this.current = index;
            _this.handleMove();
            return false;
        }
    },
    //鼠标进入
    handleMouseEnter:function(){
        var _this = this;
        return function(){
            _this.stopInterval();
        }
    },
    //鼠标移出
    handleMouseLeave:function(){
        var _this = this;
        return function(){
            _this.startInterval();
        }
    },
    //下一个
    handleNext:function(){
        var _this = this;
        return function(){
            if(_this.moveState){return false}
            _this.current ++;
            _this.handleMove();
            return false;
        }
    },
    //上一个
    handlePrev:function(){
        var _this = this;
        return function(){
            if(_this.moveState){return false}
            _this.current --;
            _this.handleMove();
            return false;
        }
    },
    //绑定事件
    bindEve:function(){
        var _this = this;
        //页码绑定
        if(_this.needPagination){
            _this.pagination.on('click',_this.handlePagination());
        }
        if(_this.needQuickButton){
            _this.nextBtn.on('click',_this.handleNext());
            _this.prevBtn.on('click',_this.handlePrev());
        }
        //开,关
        _this.node.on('mouseenter',_this.handleMouseEnter());
        _this.node.on('mouseleave',_this.handleMouseLeave());
    }
};

//******针对jquery拓展******
$.fn.carousel = function(options){
    if(!$(this).length){return}
    var opts = $.extend({
        direction : 'left',
        wait : 1000,
        time : 500,
        current : 0,
        needPagination : true,
        needQuickButton : true,
        callback:null
    },options);
    //循环实例化
    $(this).each(function(){
        new Carousel({
            node : $(this),
            direction : opts.direction,
            wait : opts.wait,
            time : opts.time,
            current : opts.current,
            needPagination : opts.needPagination,
            needQuickButton : opts.needQuickButton,
            callback:opts.callback
        }).trigger();
    });
};

sCss:

.vo-carousel{
    width: 500px;
    height: 300px;
    position: relative;
    overflow: hidden;
    //js注入
    .pagination{
        position: absolute;
        bottom: 10px;
        right: 10px;
        b{
            float: left;
            cursor: pointer;
            width: 14px;
            height: 14px;
            margin: 0 2px;
            background: #fff;
            box-shadow: 0 0 1px #ffffff;
            color: #ffffff;
            font-size: 12px;
            line-height: 14px;
            text-align: center;
            border-radius:100%;
            opacity: 0.4;
            &.on{
                color: #bb1f29;
                background: #bb1f29;
                opacity: 1;
            }
        }
    }
    .next-btn,
    .prev-btn{
        position: absolute;
        top: 50%;
        margin: -15px 0 0;
        width: 30px;
        height: 30px;
        background: rgba(0,0,0,0.8);
        cursor: pointer;
        color: #ffffff;
        text-align: center;
        line-height: 30px;
    }
    .next-btn{
        right: 0;
    }
    .prev-btn{
        left: 0;
    }
}