jQuery 无限循环滑块概念

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15876754/
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-08-26 15:57:18  来源:igfitidea点击:

Infinity Loop Slider Concepts

javascriptjqueryhtmlcss

提问by user1828928

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 what to know how to code the Slide show but what blueprint matches the requirements mention above. The main focus of my question is how to arrange the pictures to get the impression of a infinity loop Slider.

我想知道使用 JavaScript/jQuery 为网站构建 Infinity-Image-Loop-Slider 的最佳概念是什么(良好的可读代码、害虫练习代码、可重用性)?我不知道如何编码幻灯片,但什么蓝图符合上述要求。我的问题的主要焦点是如何排列图片以获得无限循环滑块的印象。

By look at Code from different Sliders I came across two solutions:

通过查看来自不同 Sliders 的代码,我发现了两种解决方案:

-change the z-Index of all Images each time the next/previous image is displayed.

- 每次显示下一个/上一个图像时更改所有图像的 z-Index。

-change the Position of the Image in the DOM.

- 更改图像在 DOM 中的位置。

But examine and understanding the code of others is very time-consuming - that's why I ask this question :-)

但是检查和理解别人的代码非常耗时——这就是我问这个问题的原因:-)

回答by Fabrizio Calderan

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

tl;dr- 示例: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 nthimage the next one to visualize is the 1st(and vice-versa).

一种无需太多努力即可创建无限图像滑块的简单方法如下:为了简单起见,您可以<n>循环滑动图像,以便在第nth 个图像之后,下一个要可视化的是1st(和反之亦然)。

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.

无论您的图像数量是多少,您最多只需要附加 2 个克隆元素。

Again for the simplicity, let say that all images are 100pxwide 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-blockand white-space: nowrapset on the container (with flexboxnow it is even easier).

再次为简单起见,假设所有图像都是100px宽的,并且它们被包裹在一个容器中,您可以将其向左/向右移动到带有overflow: hidden. 然后,所有图像都可以轻松地与容器对齐display: inline-blockwhite-space: nowrap设置在容器上(flexbox现在更容易)。

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

对于n = 4DOM 结构将是这样的:

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: -100pxor 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.

一开始,你的容器将被定位left: -100px(或者margin-left: -100px甚至更好(为了性能)transform: translateX(-100px)),所以滑块可以显示第一张图像。要从一个图像切换到另一个图像,您需要在您之前选择的同一属性上应用 javascript 动画。

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

当您的滑块当前位于第 4图像时,您必须从图像切换41c,因此我们的想法是在动画结束时执行回调,该回调很快将您的滑块包装器重新定位在真正的第一个图像偏移处(例如,您设置left: -100px到容器)

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

这是类似的,当你的滑块当前位于1个ST元素:显示你只需要从图像进行动画上一个图像14c当动画完成后,您只需移动容器,这样滑块istantly位于4 th图像偏移量(例如,您设置left: -400px为容器)。



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

您可以在上面的小提琴上看到效果:这是js/jquery我使用的最少代码(当然,代码甚至可以优化,因此项目的宽度不会硬编码到脚本中)

$(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.

如前所述,这个解决方案不需要太多的努力和谈论性能,将这种方法与没有循环的普通滑块进行比较,它只需要在滑块初始化时进行两次额外的 DOM 插入和一些(非常琐碎的)额外逻辑管理向后/向前循环。

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

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 answermay help too

注意:如果您还需要一个响应式画廊,也许这个答案也可能有所帮助

回答by ling

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

我刚刚创建了项目滑块:检查一下:https: //github.com/lingtalfi/jItemSlider/blob/master/README.md

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

它有600行代码,也许你可以简单地浏览一下。

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

它背后的想法受到 Netflix 滑块的启发(截至 2016-02-24)。

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

基本上,它使用 css 转换翻译,因为它们是浏览器中最快/最灵活的。

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

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

更多细节在这里: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

注意:我第一次尝试这个滑块实际上是克隆而不删除,它有效,但我不喜欢它: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.

此外,它是基于项目的(而不是基于像素的),最终,这就是用户所期望的,因为一切都应该是对齐的。

回答by fenmingyu

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.

te 并在我的项目中使用它。