面板支持单个,多个元素的jQuery图片轮播插件

一、先附上demo

<!doctype html>

<html>

<head>

<meta charset="utf-8">

<title>contenteditable</title>

<style>



</style>

<link href="http://a.tbcdn.cn/apps/tbtx/miiee/css/base.css" rel="stylesheet">

<link href="switchable.css" rel="stylesheet">

<style>

/*1002*380图片切换*/

.w1002-img-switch {

    position: relative;

    width: 1002px;

    height: 380px;

    overflow: hidden;

    margin: 50px auto;

}

.w1002-img-switch .switch-content {

    width: 100%;

    height: 100%;

}

.w1002-img-switch .switch-content a {

    float: left;

    display: inline;

    width: 1002px;

    height: 100%;

}

.w1002-img-switch .switch-prev-btn,

.w1002-img-switch .switch-next-btn {

    position: absolute;

    top: 160px;

    width: 61px;

    height: 61px;

    cursor: pointer;

    opacity: .3;

    filter: alpha(opacity=50);

    background-image: url(http://img01.taobaocdn.com/tps/i1/T1jGOxXqthXXahT_rS-300-150.png);

    background-repeat: no-repeat;

}

.w1002-img-switch .switch-prev-btn {

    left: 0;

    background-position: -120px 0;

}

.w1002-img-switch .switch-next-btn {

    right: 0;

    background-position: -185px 0;

}

.w1002-img-switch .switch-prev-btn:hover {

    transition: opacity .12s linear;

    opacity: 1;

    filter: alpha(opacity=100);

    background-position: -120px -70px;

}

.w1002-img-switch .switch-next-btn:hover {

    transition: opacity .12s linear;

    opacity: 1;

    filter: alpha(opacity=100);

    background-position: -185px -70px;

}

</style>

<link href="http://a.tbcdn.cn/apps/tbtx/miiee/css/home.css" rel="stylesheet">

<script src="http://code.jquery.com/jquery-1.10.2.js"></script>

</head>



<body>





<div class="miiee-content">

    <div id="first-block">

        <div id="first-block-switch" class="switch-img">

            <div class="switch-content-wrap">

                <ul class="switch-content clearfix">

                

                    <li>

                        <a href="http://miiee.taobao.com/themes/theme_133.htm" target="_blank">

                            <img src="http://gtms01.alicdn.com/tps/i1/T18ITBFmXfXXXKa4be-670-490.jpg" alt="型男奶爸正当红" title="型男奶爸正当红">

                        </a>

                    </li>

                

                    <li>

                        <a href="http://detail.tmall.com/item.htm?id=35257025329" target="_blank">

                            <img src="http://gtms04.alicdn.com/tps/i4/T1qtrGFcpbXXXKa4be-670-490.jpg" alt="都赢男装旗舰店" title="都赢男装旗舰店">

                        </a>

                    </li>

                

                    <li>

                        <a href="http://miiee.taobao.com/themes/theme_130.htm" target="_blank">

                            <img src="http://gtms01.alicdn.com/tps/i1/T1Od6EFcBaXXXKa4be-670-490.jpg" alt="蜜桃爱语" title="蜜桃爱语">

                        </a>

                    </li>

                

                    <li>

                        <a href="http://www.taobao.com/go/app/tbtx/tashuo.php" target="_blank">

                            <img src="http://gtms01.alicdn.com/tps/i1/T1BvPDFnBcXXXKa4be-670-490.jpg" alt="明星" title="明星">

                        </a>

                    </li>

                

                    <li>

                        <a href="http://miiee.taobao.com/themes/theme_131.htm" target="_blank">

                            <img src="http://gtms01.alicdn.com/tps/i1/T1mR6EFhBbXXXKa4be-670-490.jpg" alt="音乐节穿点不一样的" title="音乐节穿点不一样的">

                        </a>

                    </li>

                

                    <li>

                        <a href="http://jiuxian.tmall.com/" target="_blank">

                            <img src="http://gtms03.alicdn.com/tps/i3/T11DLvFedfXXXKa4be-670-490.jpg" alt="酒仙" title="酒仙">

                        </a>

                    </li>

                

                    <li>

                        <a href="http://miiee.taobao.com/bargain.htm" target="_blank">

                            <img src="http://gtms04.alicdn.com/tps/i4/T1tpmVFataXXXKa4be-670-490.jpg" alt="砍你妹" title="砍你妹">

                        </a>

                    </li>

                

                    <li>

                        <a href="http://nvren.taobao.com/" target="_blank">

                            <img src="http://gtms01.alicdn.com/tps/i1/T1ipfHFlpaXXcmcNbe-670-490.png" alt="拍卖" title="淘宝女人">

                        </a>

                    </li>

                

                </ul>

            </div>

            <div class="switch-nav">                

                <span class="ks-active"></span>

                <span></span>

                <span></span>

                <span></span>

                <span></span>

                <span></span>

                <span></span>

                <span></span>

            </div>

            <a class="prev" href="javascript:void(0)"></a>

            <a class="next" href="javascript:void(0)"></a>

        </div>

    </div>

</div>





<div class="w1002-img-switch">

    <div class="clearfix switch-content">

        <a href="" target="_blank">

            <img width="1002" height="380" src="http://img.la/green/gif/1002x380">

        </a>

        <a href="" target="_blank">

            <img width="1002" height="380" src="http://img.la/01531e/gif/1002x380">

        </a>

        <a href="" target="_blank">

            <img width="1002" height="380" src="http://img.la/af8003/gif/1002x380">

        </a>

        <a href="" target="_blank">

            <img width="1002" height="380" src="http://img.la/green/gif/1002x380">

        </a>

        <a href="" target="_blank">

            <img width="1002" height="380" src="http://img.la/01531e/gif/1002x380">

        </a>

        <a href="" target="_blank">

            <img width="1002" height="380" src="http://img.la/af8003/gif/1002x380">

        </a>

    </div>

    <div class="switch-trigger" style="position: absolute; right: 0; bottom: 15px;">

        <span>1</span>

        <span>2</span>

        <span>3</span>

        <span>4</span>

        <span>5</span>

    </div>

    <a class="switch-prev-btn" href="javascript:void(0);"></a>

    <a class="switch-next-btn" href="javascript:void(0);"></a>

</div>



<div id="switchable-wrap">

    <div class="switchable-content-wrap">

        <div class="clearfix switchable-content">

            <div>

                <img width="180" height="180" src="http://img01.taobaocdn.com/bao/uploaded/i1/T1okV1FmdbXXb1upjX.jpg">

            </div>

            <div>

                <img width="180" height="180" src="http://img01.taobaocdn.com/bao/uploaded/i1/T1EWd1FnJbXXb1upjX.jpg">

            </div>

            <div>

                <img width="180" height="180" src="http://img01.taobaocdn.com/bao/uploaded/i1/T1WQR0FjBcXXb1upjX.jpg">

            </div>

            <div>

                <img width="180" height="180" src="http://img01.taobaocdn.com/bao/uploaded/i1/T1dvF0FmVeXXb1upjX.jpg">

            </div>

            <div>

                <img width="180" height="180" src="http://img01.taobaocdn.com/bao/uploaded/i1/T1JRN2FdJXXXb1upjX.jpg">

            </div>

            <div>

                <img width="180" height="180" src="http://img01.taobaocdn.com/bao/uploaded/i1/T1S6F2FXhcXXb1upjX.jpg">

            </div>

            <div>

                <img width="180" height="180" src="http://img01.taobaocdn.com/bao/uploaded/i1/T179FZFkFeXXb1upjX.jpg">

            </div>

            <div>

                <img width="180" height="180" src="http://img01.taobaocdn.com/bao/uploaded/i1/T1s5VYFetgXXb1upjX.jpg">

            </div>

            <div>

                <img width="180" height="180" src="http://img01.taobaocdn.com/bao/uploaded/i1/T1UyF0FjJfXXb1upjX.jpg">

            </div>

            <div>

                <img width="180" height="180" src="http://img01.taobaocdn.com/bao/uploaded/i1/T1PXB3FltXXXb1upjX.jpg">

            </div>

            <div>

                <img width="180" height="180" src="http://img01.taobaocdn.com/bao/uploaded/i1/T1tvV0FgdeXXb1upjX.jpg">

            </div>

            <div>

                <img width="180" height="180" src="http://img01.taobaocdn.com/bao/uploaded/i1/T1nZJ3FcRXXXb1upjX.jpg">

            </div>

            <div>

                <img width="180" height="180" src="http://img01.taobaocdn.com/bao/uploaded/i1/T13stZFnJfXXb1upjX.jpg">

            </div>

            <div>

                <img width="180" height="180" src="http://img01.taobaocdn.com/bao/uploaded/i1/T11q43FepaXXb1upjX.jpg">

            </div>

        </div>            

    </div>    

    <div class="prev-btn"></div>

    <div class="next-btn"></div>

</div>

<script>

/*

 * jQuery.switchable(config) 图片轮播插件 

 * @param: {Object} 配置参数对象

 * @author: 博客园华子yjh

 */

jQuery.extend({

    /*

        图片轮播 yjh update 2013/11/25

        config = {

            wrapSelector: 外围选择器,

            contentSelector: 内容选择器,

            prevBtnSelector: 触发器(上一个),

            nextBtnSelector: 触发器(下一个),

            triggerSelector: '.switch-trigger', 触发器

            autoPlay: true, 自动轮播

            delay: 3000 延迟时间,

            interval: 3000 间隔时间,

            duration: 400 动画时间

        }

    */

    switchable: function(config) {

        var timeoutId,

            $wrap = $( config.wrapSelector ),

            $content = $wrap.find( config.contentSelector ),

            $contentParent = $content.parent().css({ position: 'relative' }),

            $panels = $content.children(),



            len = $panels.length,



            // 单个面板盒子宽度

            singlePanelBoxWidth = $panels.eq(0).outerWidth(true),



            // 视口宽度

            viewportWidth = $contentParent.width(),



            // 视口中的面板个数

            viewportPanelCount = Math.ceil(viewportWidth/singlePanelBoxWidth),



            // 视口中所有面板盒子宽度的总和

            // 即: 动画过度的像素

            viewSize = /*config.viewSize || */singlePanelBoxWidth*viewportPanelCount,



            // 所有面板占用的视口个数

            viewportCount = Math.ceil(len/viewportPanelCount),



            // 所有面板占用的视口个数 * viewSize

            totalViewSize = viewportCount*viewSize;



        if ( len <= viewportPanelCount ) {

            $( config.prevBtnSelector ).remove();

            $( config.nextBtnSelector ).remove();

            return;

        }

        

        $content.css({ width: totalViewSize + 'px', position: 'absolute' });



        var leftVal, startState = true, endState = false;

        function dynamicUpdate() {

            leftVal = Math.abs( parseInt($content.css('left'), 10) ) || 0;



            if ( leftVal < viewSize ) {

                startState = true;

                endState = false;

            }

            else if ( (leftVal + viewSize) >= totalViewSize ) {

                endState = true;

                startState = false;

            }

            else {

                startState = false;

                endState = false;

            }

        }

        

        // 激活触发器的状态

        function activateTrigger(arg) {

            var leftVal = arg;

            var idx = Math.ceil(leftVal/viewSize);

            if ( idx < 0 ) {

                idx = idx*(-1); // 需将负数转为正数

            }

            if ( idx >= viewportCount ) {

                idx = 0;

            }

            $triggers.eq(idx).addClass('trigger-active ks-active').siblings().removeClass('trigger-active ks-active');

        }

        

        function nextEvent() {

            var tempVal;

            if ( $content.filter(':animated').length === 0 ) {

                dynamicUpdate();

                tempVal = leftVal + viewSize;

                

                if ( !endState ) {

                    $content.animate({ left: -tempVal + 'px'}, config.duration || 400, 'swing', function(){

                        if ( config.triggerSelector ) {

                            activateTrigger(tempVal);

                        }

                    });

                }

                else {

                    var $outPanels = $panels.filter(function(idx){ return idx < len-viewportPanelCount });

                    $outPanels.css({ position: 'relative', left: tempVal + 'px' });

                    $content.animate({ left: -tempVal + 'px'}, config.duration || 400, 'swing', function(){

                        $outPanels.removeAttr('style');

                        $content.css({ left: 0 });



                        if ( config.triggerSelector ) {

                            activateTrigger(tempVal);

                        }

                    });

                }

            }

        }



        function prevEvent() {

            var tempVal;

            if ( $content.filter(':animated').length === 0 ) {

                dynamicUpdate();

                tempVal = -leftVal + viewSize;

                if ( !startState ) {

                    $content.animate({ left: tempVal + 'px'}, config.duration || 400, 'swing', function(){

                        if ( config.triggerSelector ) {

                            activateTrigger(tempVal);

                        }

                    });

                }

                else {

                    tempVal = -totalViewSize + viewSize;

                    var $outPanels = $panels.filter(function(idx){ return idx >= viewportPanelCount });

                    $outPanels.css({ position: 'relative', left: -totalViewSize + 'px' });

                    $content.animate({ left: viewSize + 'px'}, config.duration || 400, 'swing', function(){

                        $outPanels.removeAttr('style');

                        $content.css({ left: tempVal + 'px' });

                        

                        if ( config.triggerSelector ) {

                            activateTrigger(tempVal);

                        }

                    });

                }

            }

        }



        function autoSwitch(){

            clearTimeout(timeoutId); // fix two timeoutId execute

            timeoutId = setTimeout(function callee(){

                nextEvent();

                timeoutId = setTimeout(callee, config.interval || 3000);

            }, config.delay || 3000);

        }

        function wrapEventHandle(e){

            if ( e.type === 'mouseenter' ) {

                clearTimeout(timeoutId);

            }

            else if ( e.type === 'mouseleave' ) {

                if ( config.autoPlay ) {

                    autoSwitch();

                }

            }

        }



        if ( config.autoPlay || false ) {

            autoSwitch(); // 自动轮播

            $wrap.bind('mouseenter mouseleave', wrapEventHandle);

        }



        $( config.nextBtnSelector ).bind('click', function(){

            nextEvent();

        });

        $( config.prevBtnSelector ).bind('click', function(){

            prevEvent();

        });



        // 处理触发器

        if ( config.triggerSelector ) {

            var $triggers = $(config.triggerSelector).children().addClass('switch-item-trigger');

            $(document).delegate(config.wrapSelector + ' ' + '.switch-item-trigger', 'mouseenter click', triggerEventHandle);

        }

        function triggerEventHandle(e){

            var idx = $triggers.index( $(e.target) );

            

            if ( idx < viewportCount ) {

                var tmpVal = viewSize*idx;

                if ( $content.filter(':animated').length === 0 ) {

                    $content.animate({ left: '-' + tmpVal + 'px'}, config.duration || 400, 'swing');

                    if ( e.type === 'mouseenter' || e.type === 'click' ) {

                        $triggers.eq(idx).addClass('trigger-active ks-active').siblings().removeClass('trigger-active ks-active');

                    }

                }                

            }

        }

        return jQuery;

    }

});





$(function(){

    $.switchable({

        wrapSelector: '#first-block-switch',

        contentSelector: '.switch-content',

        prevBtnSelector: '.prev',

        nextBtnSelector: '.next',

        triggerSelector: '.switch-nav',

        autoPlay: true,

        duration: 300,

        interval: 3000

    })

    .switchable({

        wrapSelector: '.w1002-img-switch',

        contentSelector: '.switch-content',

        prevBtnSelector: '.switch-prev-btn',

        nextBtnSelector: '.switch-next-btn',

        autoPlay: true,

        duration: 300,

        interval: 4000,

        triggerSelector: '.switch-trigger'

    })

    .switchable({

        wrapSelector: '#switchable-wrap',

        contentSelector: '.switchable-content',

        prevBtnSelector: '.prev-btn',

        nextBtnSelector: '.next-btn',

        autoPlay: true,

        duration: 300,

        interval: 4000,

        delay: 3000

    });

});

</script>

</body>

</html>
View Code

二、实现思路

1、设置面板容器元素的left属性值,触发下一轮轮播,将left - viewSize(大于等于面板宽度),当前为最后一轮时,将当前显示的面板子元素的兄弟元素设置相对定位,并设置相应的位置,支持下一轮轮播循环;触发上一轮轮播,将left + viewSize,当前为首轮时,同理将当前显示的面板子元素的兄弟元素设置相对定位,并设置相应的位置,支持下上一轮轮播循环;

2、如果当前面板显示的元素只有一个时,允许有触发器,监听mouseenter事件,并显示对应的面板子元素;

3、激活面板子元素所对应的当前触发器的状态,这一部分在动画完成后实现,当前触发器的className为固定trigger-active ks-active,当然也可以自行配置;

4、当鼠标移动在整个外围容器中时,将清除自动轮播的定时器,离开时重新执行定时器,支持自动轮播,自动轮播的延迟时间为可配置项delay,其他配置项interval为自动轮播
的间隔时间,duration为动画时间,autoplay默认为false。

三、源码

/**

 * jQuery.switchable(config) 图片轮播插件 

 * @param: {Object} 配置参数对象

 * @author: 博客园华子yjh

 * update-time: 2013/12/12

 */

jQuery.extend({

    /**

        图片轮播

        config = {

            wrapSelector: 外围选择器,

            contentSelector: 内容选择器,

            prevBtnSelector: 触发器(上一个),

            nextBtnSelector: 触发器(下一个),

            triggerSelector: '.switch-trigger', 触发器

            autoPlay: true, 自动轮播

            delay: 3000 延迟时间,

            interval: 3000 间隔时间,

            duration: 400 动画时间,

            handleImgLoad: 用于懒加载的事件处理函数

        }

     */

    switchable: function(config) {

        var timeoutId,

            $wrap = $( config.wrapSelector ),

            $content = $wrap.find( config.contentSelector ),

            $contentParent = $content.parent().css({ position: 'relative' }),

            $panels = $content.children(),



            len = $panels.length,



            // 单个面板盒子宽度

            singlePanelBoxWidth = $panels.eq(0).outerWidth(true),



            // 视口宽度

            viewportWidth = $contentParent.width(),



            // 视口中的面板个数

            viewportPanelCount = Math.ceil(viewportWidth/singlePanelBoxWidth),



            // 视口中所有面板盒子宽度的总和

            // 即: 动画过度的像素

            viewSize = /*config.viewSize || */singlePanelBoxWidth*viewportPanelCount,



            // 所有面板占用的视口个数

            viewportCount = Math.ceil(len/viewportPanelCount),



            // 所有面板占用的视口个数 * viewSize

            totalViewSize = viewportCount*viewSize;



        if ( len <= viewportPanelCount ) {

            $( config.prevBtnSelector ).remove();

            $( config.nextBtnSelector ).remove();

            return;

        }

        

        $content.css({ width: totalViewSize + 'px', position: 'absolute' });



        var leftVal, startState = true, endState = false;

        function dynamicUpdate() {

            leftVal = Math.abs( parseInt($content.css('left'), 10) ) || 0;



            if ( leftVal < viewSize ) {

                startState = true;

                endState = false;

            }

            else if ( (leftVal + viewSize) >= totalViewSize ) {

                endState = true;

                startState = false;

            }

            else {

                startState = false;

                endState = false;

            }

        }

       

        // 预加载图片处理

        function handleImgLoad(tempVal, e) {

            if ( config.handleImgLoad ) {

                if ( e && $(e.target).length > 0 && $(e.target).is(config.prevBtnSelector) ) {

                    var idx = Math.abs( Math.ceil(tempVal/singlePanelBoxWidth) );

                    if (startState) {

                        idx = len - 1;

                    }

                }

                else { // 默认为next

                    idx = Math.abs( Math.ceil(tempVal/singlePanelBoxWidth) );

                    if (endState) {

                        idx = 0;

                    }

                }

                config.handleImgLoad(idx);

            }

        }               



        // 激活触发器的状态

        function activateTrigger(arg) {

            var leftVal = arg;

            var idx = Math.ceil(leftVal/viewSize);

            if ( idx < 0 ) {

                idx = idx*(-1); // 需将负数转为正数

            }

            if ( idx >= viewportCount ) {

                idx = 0;

            }

            $triggers.eq(idx).addClass('trigger-active ks-active').siblings().removeClass('trigger-active ks-active');

        }

        

        function nextEvent(e) {

            var event, tempVal, triggerCls;

            if ( $content.filter(':animated').length === 0 ) {

                dynamicUpdate();

                tempVal = leftVal + viewSize;

                handleImgLoad(tempVal, e); // 图片预加载



                if ( !endState ) {                    

                    $content.animate({ left: -tempVal + 'px'}, config.duration || 400, 'swing', function(){

                        if ( config.triggerSelector ) {

                            activateTrigger(tempVal);                            

                        }

                    });

                }

                else {

                    var $outPanels = $panels.filter(function(idx){ return idx < len-viewportPanelCount });

                    $outPanels.css({ position: 'relative', left: tempVal + 'px' });

                    $content.animate({ left: -tempVal + 'px'}, config.duration || 400, 'swing', function(){

                        $outPanels.removeAttr('style');

                        $content.css({ left: 0 });



                        if ( config.triggerSelector ) {

                            activateTrigger(tempVal);

                        }

                    });

                }

            }

        }



        function prevEvent(e) {

            var tempVal;

            if ( $content.filter(':animated').length === 0 ) {

                dynamicUpdate();

                tempVal = -leftVal + viewSize;                

                handleImgLoad(tempVal, e); // 图片预加载

                

                if ( !startState ) {

                    $content.animate({ left: tempVal + 'px'}, config.duration || 400, 'swing', function(){

                        if ( config.triggerSelector ) {

                            activateTrigger(tempVal);

                        }

                    });

                }

                else {

                    tempVal = -totalViewSize + viewSize;

                    var $outPanels = $panels.filter(function(idx){ return idx >= viewportPanelCount });

                    $outPanels.css({ position: 'relative', left: -totalViewSize + 'px' });

                    $content.animate({ left: viewSize + 'px'}, config.duration || 400, 'swing', function(){

                        $outPanels.removeAttr('style');

                        $content.css({ left: tempVal + 'px' });

                        

                        if ( config.triggerSelector ) {

                            activateTrigger(tempVal);

                        }

                    });

                }

            }

        }



        function autoSwitch(){

            clearTimeout(timeoutId); // fix two timeoutId execute

            timeoutId = setTimeout(function callee(){

                nextEvent();

                timeoutId = setTimeout(callee, config.interval || 3000);

            }, config.delay || 3000);

        }

        function wrapEventHandle(e){

            if ( e.type === 'mouseenter' ) {

                clearTimeout(timeoutId);

            }

            else if ( e.type === 'mouseleave' ) {

                if ( config.autoPlay ) {

                    autoSwitch();

                }

            }

        }



        if ( config.autoPlay || false ) {

            autoSwitch(); // 自动轮播

            $wrap.bind('mouseenter mouseleave', wrapEventHandle);

        }



        $( config.nextBtnSelector ).bind('click', nextEvent);

        $( config.prevBtnSelector ).bind('click', prevEvent);



        // 处理触发器

        if ( config.triggerSelector ) {

            var $triggers = $(config.triggerSelector).children().addClass('switch-item-trigger');

            $(document).delegate(config.wrapSelector + ' ' + '.switch-item-trigger', 'mouseenter click', triggerEventHandle);

        }

        function triggerEventHandle(e){

            var idx = $triggers.index( $(e.target) );



            if ( idx < viewportCount ) {

                var tempVal = viewSize*idx;

                config.handleImgLoad(idx);

                if ( $content.filter(':animated').length === 0 ) {

                    $content.animate({ left: '-' + tempVal + 'px'}, config.duration || 400, 'swing');

                    if ( e.type === 'mouseenter' || e.type === 'click' ) {

                        $triggers.eq(idx).addClass('trigger-active ks-active').siblings().removeClass('trigger-active ks-active');

                    }

                }

            }

        }

        return jQuery;

    }

});

 

PS: 实现的过程操作均在动画完成之后执行的,就是用户必须在轮播完后,进行下一次的上下轮播,这也算是我的实现瓶劲,望高手多多指教

转载请注明出处博客园,华子yjh

你可能感兴趣的:(jquery图片轮播)