如何修改Elastislide,使其无限循环

时间:2012-06-02 05:19:08

标签: javascript carousel infinite-loop responsive-design

我一直在寻找能够同时显示多张图像的图像轮播,响应并无限循环。

Elastislide似乎是最合适的(http://tympanus.net/Development/Elastislide/index2.html)。

我能找到的唯一其他实用选择是John Nikolakis的液体旋转木马,它看起来有点旧,不那么优雅。

我使用与http://www.w3schools.com/js/js_timing.asp所示的clearTimeout()方法类似的方法使Elastislide自动播放(排序),但一旦到达终点就停止了,因为时间只是调用下一个按钮(.es-nav-next)。

我希望有人可以帮助我修改Elastislide以使其无限循环 - 或者我愿意接受符合我的3项要求(上面列出的)的不同解决方案的建议。

目前我正在进行OpenCart的本地安装,但我可以提供一个静态样本并提供链接,如果有帮助的话。

任何帮助或建议都会非常感激,我花了很多时间在这上面,因为我是javascript的一个完整的业余爱好者:)

7 个答案:

答案 0 :(得分:9)

Elastislide代码已经发展,上述解决方案无效。所以我开发了自己的解决方案。

此代码使弹性滑动自动播放,当到达最后一张幻灯片时,它返回到第一张幻灯片,比无限循环卡车更符合人体工程学。

此代码应添加到var _initEvents

之后的self = this;函数中
var translation = 0;
// width/height of an item ( <li> )
var itemSpace = this.options.orientation === 'horizontal' ? this.$items.outerWidth( true ) : this.$items.outerHeight( true );
// total width/height of the <ul>
var totalSpace = this.itemsCount * itemSpace;
// visible width/height
var visibleSpace = this.options.orientation === 'horizontal' ? this.$carousel.width() : this.$carousel.height();
//slide auto
window.setInterval(function(){
    //test if we should go to next slide or return to first slide
    if(totalSpace > translation + visibleSpace)
    {
        //go to next slide
        self._slide('next');
        //update translation
        translation += visibleSpace;
    }
    else
    {
        //return to first slide (infinite loop is too bad for ergonomics)
        self._slideTo(0);
        //set translation to 0
        translation = 0;
    }
}, 7000);

答案 1 :(得分:2)

如果页面上显示的元素多于其他元素,则此代码会创建无限循环,保留动画并在两侧显示导航按钮。 _toggleControls功能与原始版本保持一致。

// modified version of _slide
_slide              : function( dir, val, anim, callback ) {

        // if animating return
        if( this.$slider.is(':animated') )
            return false;

        // current margin left
        var ml      = parseFloat( this.$slider.css('margin-left') );

        // val is just passed when we want an exact value for the margin left (used in the _slideToCurrent function)
        if( val === undefined ) {

            // how much to slide?
            var amount  = this.fitCount * this.itemW, val;

            if( amount < 0 ) return false;

            // make sure not to leave a space between the last item / first item and the end / beggining of the slider available width
            if( dir === 'right' && this.sliderW - ( Math.abs( ml ) + amount ) < this.visibleWidth ) {
                for (var i=0;i<this.fitCount;i++) { // add elements
                    this.$slider.css('margin-left', '+=' + this.itemW );
                    this.$slider.append( this.$slider.children('li:first').clone() ) ;
                    this.$slider.children('li:first').remove();
                }
            } else if ( dir === 'left' && Math.abs( ml ) - amount < 0 ) {
                for (var i=0;i<this.fitCount;i++) { // add elements
                    this.$slider.css('margin-left', '-=' + this.itemW );
                    this.$slider.prepend( this.$slider.children('li:last').clone() ) ;
                    this.$slider.children('li:last').remove();
                }
            }

            ( dir === 'right' ) ? val = '-=' + amount : val = '+=' + amount

        }
        else {
            var fml     = Math.abs( val ); // future margin left

            if( Math.max( this.sliderW, this.visibleWidth ) - fml < this.visibleWidth ) {
                val = - ( Math.max( this.sliderW, this.visibleWidth ) - this.visibleWidth );
                if( val !== 0 )
                    val += this.options.margin; // decrease the margin left if not on the first position

                // show / hide navigation buttons
                this._toggleControls( 'right', -1 );
                fml = Math.abs( val );
            }

            // show / hide navigation buttons
            if( this.fitCount < this.itemsCount )
                this._toggleControls( 'left', 1 );
            else
                this._toggleControls( 'left', -1 );

            if( Math.max( this.sliderW, this.visibleWidth ) - this.visibleWidth > fml + this.options.margin )   
                this._toggleControls( 'right', 1 );
            else
                this._toggleControls( 'right', -1 );

        }

        $.fn.applyStyle = ( anim === undefined ) ? $.fn.animate : $.fn.css;

        var sliderCSS   = { marginLeft : val };

        var instance    = this;

        this.$slider.applyStyle( sliderCSS, $.extend( true, [], { duration : this.options.speed, easing : this.options.easing, complete : function() {
            if( callback ) callback.call();
        } } ) );

    },

答案 2 :(得分:1)

我是通过黑客攻击toggleControls()函数来实现的,而不是隐藏导航以附加第一个项目/前置最后一个项目。当您处于项目的开头/结尾时,金额的自动更正实际上有助于实现这一目的。不幸的是,如果使用缓和,它会破坏动画。

// modified version of _toggleControls
    _toggleControls     : function( dir, status ) {

        // show / hide navigation buttons
        if( dir && status ) {
            if( status === 1 )
                ( dir === 'right' ) ? this.$navNext.show() : this.$navPrev.show();
            else
                if ( dir === 'right' ) {

                    this.$slider.append( this.$slider.children('li:first').clone() ) ;
                    this.$slider.children('li:first').remove();
                } else {

                    this.$slider.prepend( this.$slider.children('li:last').clone() ) ;
                    this.$slider.children('li:last').remove();
                }
        }
        else if( this.current >= this.itemsCount - 1 || this.fitCount >= this.itemsCount )
                this.$navNext.hide();

    },

答案 3 :(得分:1)

我遇到了与OP相同的问题,但无法获得上述任何一种解决方案。不确定我是否做错了什么,或者自从那些解决方案被编写后Elastislide代码发生了变化。

我找到了这个插件,它似乎满足了OP的所有标准:具有自动播放和无限循环的响应式旋转木马。

http://caroufredsel.dev7studios.com/

希望这能帮助找到这篇文章的其他人与我一样。

答案 4 :(得分:1)

在 - var instance = this之后,在_initEvents函数中添加此代码;使弹性滑动自动播放。

window.setInterval(function(){
                instance._slide('right');
            }, 7000);

答案 5 :(得分:0)

RoxySka答案的略微修改版本,添加了使用初始化设置打开和关闭它的功能。

这将使Elastislide自动播放,当在最后一张幻灯片上时,它将返回到第一张幻灯片。

$.Elastislide.defaults之后将此代码添加到start : 0,对象:

// autoplay true || false
autoplay : true,

然后,您可以在设置选项时设置autoplay值(true或false),就像您在上面的示例代码中尝试的那样。

此代码应添加到_initEvents

之后的self = this;函数中
     if(this.options.autoplay == true){
            var translation = 0;
            // width/height of an item ( <li> )
            var itemSpace = this.options.orientation === 'horizontal' ? this.$items.outerWidth( true ) : this.$items.outerHeight( true );
            // total width/height of the <ul>
            var totalSpace = this.itemsCount * itemSpace;
            // visible width/height
            var visibleSpace = this.options.orientation === 'horizontal' ? this.$carousel.width() : this.$carousel.height();
            //slide auto
            window.setInterval(function(){
                //test if we should go to next slide or return to first slide
                if(totalSpace > translation + visibleSpace)
                {
                    //go to next slide
                    self._slide('next');
                    //update translation
                    translation += visibleSpace;
                }
                else
                {
                    //return to first slide
                    self._slideTo(0);
                    //set translation to 0
                    translation = 0;
                }
            }, 7000);
        }

请注意,随着Elastislide越过v1.1.0,此代码在将来的版本中可能无效。

答案 6 :(得分:0)

这是旧版弹力纤维,也许这段代码可以帮助别人。

这不是一个无限循环,但是当你到达缩略图轮播的末尾然后点击下一步它会回到动画到初始状态,如果你在开头并按下上一个按钮它将一直移动到持续缩略图像。

首先你必须评论(或删除) _toggleControls 的所有行,这样我们就可以避免导航中的按钮被隐藏。

然后更改 _slide

的代码
        _slide              : function( dir, val, anim, callback ) {

        var ml      = parseFloat( this.$slider.css('margin-left') );

        // val is just passed when we want an exact value for the margin left (used in the _slideToCurrent function)
        if( val === undefined ) {

            // how much to slide?
            var amount  = this.fitCount * this.itemW, val;

            if( amount < 0 ) return false;
            // make sure not to leave a space between the last item / first item and the end / beggining of the slider available width
            if( dir === 'right' && this.sliderW - ( Math.abs( ml ) + amount ) < this.visibleWidth ) {                   
                amount  = this.sliderW - ( Math.abs( ml ) + this.visibleWidth ) - this.options.margin; // decrease the margin left
                //Loop to the beginning
                if (amount === 0) {
                    this.current = 0;                       
                    amount = this.sliderW - this.visibleWidth;
                    anim = undefined;
                    dir = 'left';
                }
            }
            else if( dir === 'left' && Math.abs( ml ) - amount < 0 ) {
                amount  = Math.abs( ml );
                //Loop to the end
                if ($(".es-carousel ul").css("margin-left") === "0px") {
                    this.current = this.itemsCount - 1;
                    amount = -(this.sliderW - this.visibleWidth);                       
                    anim = undefined;
                }
            }
            else {
                var fml; // future margin left
                ( dir === 'right' ) 
                    ? fml = Math.abs( ml ) + this.options.margin + Math.abs( amount )
                    : fml = Math.abs( ml ) - this.options.margin - Math.abs( amount );                      
            }

            ( dir === 'right' ) ? val = '-=' + amount : val = '+=' + amount;                
        }
        else {
            var fml     = Math.abs( val ); // future margin left

            if( Math.max( this.sliderW, this.visibleWidth ) - fml < this.visibleWidth ) {
                val = - ( Math.max( this.sliderW, this.visibleWidth ) - this.visibleWidth);
                if( val !== 0 )                     
                    val += this.options.margin; // decrease the margin left if not on the first position                        
                fml = Math.abs( val );
            }
        }

        $.fn.applyStyle = ( anim === undefined ) ? $.fn.animate : $.fn.css;

        var sliderCSS   = { marginLeft : val };

        var instance    = this;

        this.$slider.stop().applyStyle( sliderCSS, $.extend( true, [], { duration : this.options.speed, easing : this.options.easing, complete : function() {
            if( callback ) callback.call();
        } } ) );

    },