Infinity Loop Slider Concepts

后端 未结 3 759
星月不相逢
星月不相逢 2020-11-29 21:54

I wonder what are the best(good readable code, pest practice code,reusability) concepts to build a Infinity-Image-Loop-Slider for a Website using JavaScript/jQuery? I dont w

相关标签:
3条回答
  • 2020-11-29 22:20

    tl;dr - JSBin Example: http://jsbin.com/ufoceq/8/


    A simple approach to create an infinite image slider without too much effort is as follows: let say for the sake of simplicity that you have <n> images to slide in a loop, so that after the nth image the next one to visualize is the 1st (and vice-versa).

    The idea is to create a clone of first and last image so that

    • the clone of the last image is prepended before the first one;
    • the clone of the first image is appended after the last one.

    Whatever is the amount of your images, you will need to append at most only 2 cloned elements.

    Again for the simplicity, let say that all images are 100px wide and they're wrapped in a container that you move left/right into a clipped mask with overflow: hidden. Then, all images can be easily aligned in a row with display: inline-block and white-space: nowrap set on the container (with flexbox now it is even easier).

    For n = 4 The DOM structure would be something like this:

    offset(px)     0       100     200     300     400     500
    images         |   4c   |   1   |   2   |   3   |   4   |   1c
                                                       
    /*                 ^^                                       ^^
           [ Clone of the last image ]              [ Clone of the 1st image ]
    */
    

    At the beginning, your container will be positioned with left: -100px (or also margin-left: -100px or even better (for a matter of performance) transform: translateX(-100px) ), so the slider can show the first image. To switch from an image to another you will need to apply a javascript animation over the same property you've previously chosen.

    When your slider is currently at the 4th image, you have to switch from image 4 to 1c, so the idea is to execute a callback at the end of the animation that soon reposition your slider wrapper at the real 1st image offset (e.g. you set left: -100px to the container)

    This is analogous when your slider is currently positioned on the 1st element: to show the previous image you just need to perform an animation from image 1 to 4c and when animation has been completed you just move the container so the slider is istantly positioned at the 4th image offset (e.g. you set left: -400px to the container).


    You can see the effect on the above fiddle: this is the minimal js/jquery code I used (of course the code can be even optimized so the width of the items is not hardcoded into the script)

    $(function() {
     
      var gallery = $('#gallery ul'),
          items   = gallery.find('li'),
          len     = items.length,
          current = 1,  /* the item we're currently looking */
          
          first   = items.filter(':first'),
          last    = items.filter(':last'),
          
          triggers = $('button');
      
      /* 1. Cloning first and last item */
      first.before(last.clone(true)); 
      last.after(first.clone(true)); 
      
      /* 2. Set button handlers */
      triggers.on('click', function() {
    
        var cycle, delta;
        
        if (gallery.is(':not(:animated)')) {
         
            cycle = false;
            delta = (this.id === "prev")? -1 : 1;
            /* in the example buttons have id "prev" or "next" */  
        
            gallery.animate({ left: "+=" + (-100 * delta) }, function() {
          
                current += delta;
           
                /** 
                 * we're cycling the slider when the the value of "current" 
                 * variable (after increment/decrement) is 0 or when it exceeds
                 * the initial gallery length
                 */          
                cycle = (current === 0 || current > len);
           
                if (cycle) {
                    /* we switched from image 1 to 4-cloned or 
                       from image 4 to 1-cloned */
                    current = (current === 0)? len : 1; 
                    gallery.css({left:  -100 * current });
                }
            });   
         }
        
      });
    });
    

    As mentioned before, this solution doesn't require really much effort and talking about performance, comparing this approach to a normal slider without looping, it only requires to make two additional DOM insertion when the slider is initialized and some (quite trivial) extra logic to manage a backward/forward loop.

    Here is another example when you see two elements at once: in that case you need to clone more elements and make some simple changes to the logic

    https://codepen.io/fcalderan/pen/bGbjZdz

    I don't know if a simpler or better approach exists, but hope this helps anyway.

    Note: if you need to also have a responsive gallery, maybe this answer may help too

    0 讨论(0)
  • 2020-11-29 22:23

    I've just created the item slider: check it out: https://github.com/lingtalfi/jItemSlider/blob/master/README.md

    It's 600 lines of code, maybe you can simply browse it.

    The idea behind it is inspired by the netflix slider (as of 2016-02-24).

    Basically, it uses css transform translations, because those are the fastest/slickest in a browser.

    http://eng.wealthfront.com/2015/05/19/performant-css-animations/

    Now the basic concept behind the slide movement, is that you only display the current visible slice, but you also have one invisible slice on the left, and another invisible slice on the right.

    And, you also have two extra items, one on each side, so that your items look like this:

    previous items - prev extra item - main items - next extra item - next items

    Only the main items are visible. The extra items are partially visible. The previous and next items are invisible.

    More details here: https://github.com/lingtalfi/jItemSlider/blob/master/doc/conception.md

    Now when you slide to the right (for instance), you basically append more items to the right side, and then remove those from the left side.

    This technique is the greatest I've encountered so far, because you don't deal with a long list of items (using cloning without removing the invisible items), which can make your animation slower.

    Note: my first try of this slider was actually cloning without removing, it works, but I don't like it: https://github.com/lingtalfi/jInfiniteSlider

    Also, it's item based (rather than pixels based), and in the end, that's what the user expects because everything is always aligned, as it should be.

    0 讨论(0)
  • 2020-11-29 22:23

    Thanks a lot of this article! I had update and used above code. I hope this will help everyone. Poor developer.

    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title>Directive slider</title>
        <style>
            /* 四联切换焦点图 */
            .slides-wrapper{ position: relative;  width: 100%;  margin: 10px 0; }
            .gallery { position: relative;  width: 1200px;  height: 180px;  overflow:hidden;  }
            .gallery ul {  font-size: 0;  white-space: nowrap;  position: absolute;  top: 0;  left: -1200px;  margin: 0; padding: 0;  }
            .gallery li {  display: inline-block;  vertical-align: top;  width: 1200px;  height: 180px;  white-space: normal;  }
            .gallery li img{  width: 298px;  height:180px;  padding: 1px;  }
            .gallery .arrow { background: url(/shop/templates/default/images/home_bg.png) no-repeat; background-size: 150px 223px; width: 35px; height: 70px; position: absolute; z-index: 2; top: 50px; cursor: pointer; opacity: 0;}
            .gallery .prev { background-position: 1px -92px; left: 0;}
            .gallery .next { background-position: -30px -92px; right: 0px;}
        </style>
        <style type="text/css">
            .demo_wrapper{
                margin: 0 auto;
                width: 1200px;
            }
            .demo_wrapper .title{
                text-align: center;
            }
        </style>
    </head>
    <body>
    <div class="demo_wrapper">
        <div class="title">
            <h1>Directive slider (Published by fenmingyu)</h1>
        </div>
        <!-- demo content -->
        <div class="slides-wrapper">
            <div class="gallery" id="top_sale_gallery">
                <ul>
                    <li>
                        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-1-1.jpg?234" alt=""></a>
                        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-1-2.jpg?752" alt=""></a>
                        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-1-3.jpg?320" alt=""></a>
                        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-1-4.jpg?365" alt=""></a>
                    </li>
                    <li>
                        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-2-1.jpg?852" alt=""></a>
                        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-2-2.jpg?746" alt=""></a>
                        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-2-3.jpg?525" alt=""></a>
                        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-2-4.jpg?550" alt=""></a>
                    </li>
                </ul>
                <div class='arrow prev'></div>
                <div class='arrow next'></div>
            </div>
            <div class="gallery" id="top_goods_gallery">
                <ul>
                    <li>
                        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-3-1.jpg?793" alt=""></a>
                        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-3-2.jpg?180" alt=""></a>
                        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-3-3.jpg?550" alt=""></a>
                        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-3-4.jpg?851" alt=""></a>
                    </li>
                    <li>
                        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-1-1.jpg?234" alt=""></a>
                        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-1-2.jpg?752" alt=""></a>
                        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-1-3.jpg?320" alt=""></a>
                        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-1-4.jpg?365" alt=""></a>
                    </li>
                    <li>
                        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-2-1.jpg?852" alt=""></a>
                        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-2-2.jpg?746" alt=""></a>
                        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-2-3.jpg?525" alt=""></a>
                        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-2-4.jpg?550" alt=""></a>
                    </li>
                </ul>
                <div class='arrow prev'></div>
                <div class='arrow next'></div>
            </div>
            <div style="clear: both;"></div>
        </div>
    </div>
    
    </body>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script type="text/javascript">
        $(function() {
            $.fn.gallery = function(settings) {
                var defaults = {
                    time: 3000,
                    direction:1
                };
                var settings = $.extend(defaults, settings);
                var gallery_wrapper = $(this),
                    gallery = gallery_wrapper.find('ul'),
                    items   = gallery.find('li'),
                    len     = items.length,
                    current = 1,  /* the current item we're looking */
                    first   = items.filter(':first'),
                    last    = items.filter(':last'),
                    w = gallery.find('li').width(),
                    triggers = gallery_wrapper.find('.arrow');
                var show_slide = function(direction,w){
                    gallery.animate({ left: "+=" + (-w * direction) }, function() {
    
                        current += direction;
    
                        /**
                         * we're cycling the slider when the the value of "current"
                         * variable (after increment/decrement) is 0 or when it exceeds
                         * the initial gallery length
                         */
                        cycle = !!(current === 0 || current > len);
    
                        if (cycle) {
                            /* we switched from image 1 to 4-cloned or
                             from image 4 to 1-cloned */
                            current = (current === 0)? len : 1;
                            gallery.css({left:  -w * current });
                        }
                    });
                };
                var picTimer = setInterval(function() {
                            show_slide(settings.direction,w);
                        },
                        settings.time);
                return this.each(function(){
    
                    /* 1. Cloning first and last item */
                    first.before(last.clone(true));
                    last.after(first.clone(true));
                    /* 2. Set button handlers */
                    triggers.on('click', function() {
                        if (gallery.is(':not(:animated)')) {
    
                            var cycle = false;
                            settings.direction = ($(this).hasClass('prev'))? -1 : 1;
                            /* in the example buttons have id "prev" or "next" */
                            show_slide(settings.direction,w);
                        }
                        clearInterval(picTimer);
                        picTimer = setInterval(function() {
                                    show_slide(settings.direction,w);
                                },
                                settings.time);
                    });
                    /* hover show arrows*/
                    show_slide(settings.direction,w);
    
                    gallery_wrapper.hover(function() {
                        $(this).find(".arrow").css("opacity", 0.0).stop(true, false).animate({
                                    "opacity": "0.3"
                                },
                                300);
                    },function(){
                        $(this).find(".arrow").css("opacity", 0.3).stop(true, false).animate({
                                    "opacity": "0"
                                },
                                300);
                    });
                });
            };
            $('#top_goods_gallery.gallery').gallery();
            $('#top_sale_gallery.gallery').gallery({
                time: 5000,
                direction:-1
            });
        });
    </script>
    </html>

    te and use this in my project.

    0 讨论(0)
提交回复
热议问题