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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10859998/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 11:17:46  来源:igfitidea点击:

How to modify Elastislide so it loops infinitely

javascriptcarouselinfinite-loopresponsive-design

提问by Kirstan

I've been searching for an image carousel that will display several images at once, is responsive and loops infinitely.

我一直在寻找一个图像轮播,它可以一次显示多张图像,响应迅速并且无限循环。

Elastislide seems to be the most suitable ( http://tympanus.net/Development/Elastislide/index2.html).

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

The only other practical option I've been able to find is Liquid Carousel by John Nikolakis which seems to be a fair bit older and less elegant.

我能找到的唯一其他实用的选择是 John Nikolakis 的 Liquid Carousel,它似乎有点老,不太优雅。

I've got Elastislide to autoplay (sort of), using a similar method to the The clearTimeout() Method shown at http://www.w3schools.com/js/js_timing.asp, but once it reaches the end it stops, as the timing is just calling the next button (.es-nav-next).

我已经让 Elastislide 自动播放(有点),使用类似于http://www.w3schools.com/js/js_timing.asp 上显示的 clearTimeout() 方法的方法,但一旦到达终点,它就会停止,因为时间只是调用下一个按钮(.es-nav-next)。

I'm hoping someone can help me with modifying Elastislide to make it loop infinitely - or I'm open to suggestions for a different solution which meets my 3 requirements (listed above).

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

At the moment I'm working on a local installation of OpenCart but I can put up a static sample and provide a link if that helps.

目前,我正在本地安装 OpenCart,但如果有帮助,我可以提供静态示例并提供链接。

Any help or advice would be greatly appreciated, have spent many hours on this so far as I'm a complete amateur at javascript :)

任何帮助或建议将不胜感激,到目前为止我已经在这方面花费了很多时间,因为我是 javascript 的完全业余爱好者:)

回答by roxySka

Elastislide code has evolved and the above solution does not work. So I have developed my own solution.

Elastislide 代码已经演变,上述解决方案不起作用。所以我开发了自己的解决方案。

This code makes elastislide autoplay and when arrived at last slide it returns to the first slide to be more ergonomic than the infinite loop caroussel.

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

This code should be added in the _initEventsfunction after var self = this;

此代码应添加在_initEvents函数中 var 之后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);

回答by Lukasz

This code creates an infinite loop, preserves animations and shows navigation buttons on both sides if there are more elements than displayed on page. The _toggleControlsfunction remains the same as in the original version.

这段代码创建了一个无限循环,如果元素多于页面上显示的元素,则保留动画并在两侧显示导航按钮。该_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();
        } } ) );

    },

回答by stevecomrie

I was having the same trouble as the OP, but couldn't get either of the above solutions to work. Not sure if I was doing something wrong or if the Elastislide code had changed since those solutions were written.

我遇到了与 OP 相同的麻烦,但无法使上述任何一种解决方案起作用。不确定是我做错了什么,还是 Elastislide 代码在编写这些解决方案后发生了变化。

I found this plugin, which seems to satisfy all the same criteria that the OP had: responsive carousel with auto-play and infinite loop.

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

http://caroufredsel.dev7studios.com/

http://caroufredsel.dev7studios.com/

Hopefully this helps someone else that finds this article the same way I did.

希望这可以帮助其他像我一样找到这篇文章的人。

回答by Tristan

Add this code in the _initEvents function after - var instance = this; to make the elastislide autoplay.

在 _initEvents 函数中 - var instance = this; 之后添加这段代码;使弹性幻灯片自动播放。

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

回答by Maxim Krizhanovsky

I did it by hacking the toggleControls() function, instead of hiding the navigation to append the first item / prepend the last item. The auto-correction of amount when you are in the beginning / end of the items actually helped to do the trick. Unfortunatelly it breaks the animation, if easing is used.

我是通过修改 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();

    },

回答by ORyan

Slightly modified version of RoxySka's answer, adding the ability to turn it on and off with the initialization settings.

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

This will make Elastislide autoplay and when on the last slide it will return to the first slide.

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

Add this code to the $.Elastislide.defaultsobject after start : 0,:

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

// autoplay true || false
autoplay : true,

You'll then have the ability to set the autoplayvalue (true or false) when you set the options up, as you were trying to do in your example code above.

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

This code should be added in the _initEventsfunction after var self = this;

此代码应添加在_initEvents函数中 var 之后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);
        }


Be aware that as Elastislide evolves past v1.1.0 this code may not work in future versions.

请注意,随着 Elastislide 的发展超过 v1.1.0,此代码在未来版本中可能无法使用。

回答by GmM

This is for an old version of elastislide, Maybe this code could help someone.

这是针对旧版本的 elasticslide,也许这段代码可以帮助某人。

This is not an infinite loop, but when you get to the end of the thumbnail carousel and click on next it goes back with animation to the initial state, and if you're at the beginning and press the prev button it will move till the lasts thumbnail images.

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

First You have to comment (or removed) all the lines of _toggleControls, in this way we avoid that the buttons in navigation get hiden.

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

And then change the code of _slide:

然后更改_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();
        } } ) );

    },