【问题标题】:jquery/javascript loop slider itemjquery/javascript 循环滑块项目
【发布时间】:2023-03-24 16:01:01
【问题描述】:

我创建了一个带有动画效果的基本滑块,

我正在使用transform: translate3d 向左或向右移动滑块,但在如何使其循环并无限向左或向右滑动时遇到了问题并且有点迷失。

我正在努力做到这一点,当您单击左或右时,它会不断显示和旋转图像。

我也想用 z-index 平滑过渡,但似乎不可能。

这是我完成的工作的 jsFiddle https://jsfiddle.net/wo67h4n9/

这是 HTML 代码

<div class="vs-slider">
  <div class="vss-wrap">
    <div class="item active"><img src="http://lorempixel.com/430/280/sports" alt="Slider Item" width="430" height="280"></div>
    <div class="item"><img src="http://lorempixel.com/430/280/animals" alt="Slider Item" width="430" height="280"></div>
    <div class="item"><img src="http://lorempixel.com/430/280/nature" alt="Slider Item" width="430" height="280"></div>
  </div>
  <ul class="vss-nav">
    <li class="prev">&lt;</li>
    <li class="next">&gt;</li>
  </ul>
</div>

jQuery

;( function($) {
    $(document).ready(function() {
        $('.vs-slider .item').each( function() {
            $(this).css('z-index', $('.vs-slider .item').length - $('.vs-slider .item').index(this));
        });

        $('.vss-nav').on('click', '.prev, .next', function() {
            var active = $(this).closest('.vs-slider').find('.item.active');
            if ( $(this).hasClass('next') ) {
                vss_moveleft($('.vs-slider'));
                active.next().addClass('active');
            } else {
                vss_moveleft( $('.vs-slider'), 'right');
                active.prev().addClass('active');
            }
            active.removeClass('active');
        });

        function vss_moveleft( slider, type = 'left' ) {
            var itemWidth = slider.find('.item').outerWidth() - 299,
            itemTotal = slider.find('.item').length,
            currentOff = slider.find('.vss-wrap').position().left,
            movemVal = type === 'left' ? currentOff - itemWidth : currentOff + itemWidth;
            slider.find('.vss-wrap').css('transform', 'translate3d('+ movemVal +'px, 0px, 0px)');

        }
    });
})(jQuery);

CSS

body {
  background: #222
}
.vs-slider {
  position: relative;
  overflow: hidden;    
  max-height: 290px;
  max-width: 500px;
}
.vs-slider img {
    margin: 0;
    vertical-align: top;
}
.vs-slider .vss-wrap {
    min-width: 90VW;
    transform: translate3d(0px, 0px, 0px);
    transition: all 0.5s ease 0s;
}
.vs-slider .vss-wrap::after {
    clear: both;
    width: 100%;
    display: block;
    content: "";
}
.vs-slider .item {
    float: left;
    border: 1px solid #fff;
    transform: scale(.7);
    position: relative;
    z-index: 1;
    transition: all 1s ease 0s;
    margin-right: -299px;
}
.vs-slider .item.active {
    transform: scale(1);
    z-index: 20 !important;
}
.vs-slider .item:not(.active) {
    z-index: 0;
    cursor: pointer;
}
.vss-nav {
    position: absolute;
    margin: 0;
    padding: 0;
    right: 5px;
    bottom: 0;
}
.vss-nav li {
    display: inline-block;
    color: #fff;
    margin: 0 5px;
    cursor: pointer;
}

不胜感激。

谢谢

【问题讨论】:

    标签: javascript jquery css-animations


    【解决方案1】:

    嘿,你做了一个多么有趣的问题,你需要关心一些事情来实现你的目标,所以我会解释你错过了什么。

    1. 你可以使用纯css来应用过渡而不需要JS,所以你需要的东西是Siblings Selectors,这将帮助你将样式应用到特定元素右侧的所有元素。

    例如:假设我们有一个简单的标记,例如

    <div>
      <div class="item active">
      </div>
      <div class="item">
      </div>
      <div class="item">
      </div>
      <div class="item">
      </div>
    </div>
    
    // Styles.css
    
    .item.active ~ .item {
      background: blue;
    }
    

    上面的样式将应用于item 类位于.item.active 元素右侧的所有元素

    1. 为所有item 类应用样式以将它们扔到左侧。

    2. .item.active 元素应用样式,使其成为唯一显示的元素。

    3. 1234563并将其放在末尾,用于下一种情况,并取最后一个元素并将其放在前一种情况的开头。
    4. 您需要检查滑块何时开始,如果第一个元素处于活动状态,那么您需要克隆所有元素并将它们以相反的顺序放置在第一个元素之前。

      李>

    所以,不用多说,这里你需要一个工作示例,它将帮助你理解这个不定式滑块的功能。

    ;( function($) {
        $(document).ready(function() {
        		/*
            This function will check if the active class is in the first element then we will clone all elements at the left side of the first element to make it circular sliding
            */
          	function cloneElementsIfStartAtZero() {
              var firstItem = $('.item').first();
              var isActiveFirst = firstItem.hasClass('active');
    
              if (isActiveFirst) {
                var last = firstItem;
                $($('.item').get().reverse()).each(function(){
                  var current = $(this).clone().removeClass('active');
                  last.before(current);
                  last = current;
                });
              }
            }
        
        		cloneElementsIfStartAtZero();
    
            $('.vss-nav').on('click', '.prev, .next', function() {
            		// we get the active, first, and last elements
                var active = $('.item.active');
                var first = $('.item').first();
                var last = $('.item').last();
                
                // if click at next arrow
                
                if ( $(this).hasClass('next') ) {
                		// check if next element is the last, then take the first element and set it to the last element
                    if(active.next().next().length === 0) {
                    	last.after(first);
                    }
                    // apply active class to make transition
                    active.next().addClass('active');
                } else {
                		// check if prev element is the first, then take last element and set it before the first element
                		if(active.prev().length === 0 || active.prev().prev().length === 0) {
                    	first.before(last);
                    }
                    // then appy active class to apply transition
    								active.prev().addClass('active');
                }
                active.removeClass('active');
            });
    
            function vss_moveleft( slider, type = 'left' ) {
                var itemWidth = slider.find('.item').outerWidth() - 299,
                itemTotal = slider.find('.item').length,
                currentOff = slider.find('.vss-wrap').position().left,
                movemVal = type === 'left' ? currentOff - itemWidth : currentOff + itemWidth;
                slider.find('.vss-wrap').css('transform', 'translate3d('+ movemVal +'px, 0px, 0px)');
    
            }
        });
    })(jQuery);
    body {
      background: #222
    }
    .vs-slider {
      position: relative;
     /* overflow: hidden;*/    
      max-height: 290px;
      max-width: 500px;
      margin: auto;
    }
    .vs-slider img {
    	margin: 0;
    	vertical-align: top;
    }
    .vs-slider .vss-wrap {
    	min-width: 90VW;
    	transform: translate3d(0px, 0px, 0px);
    	transition: all 0.5s ease 0s;
    }
    .vs-slider .vss-wrap::after {
        clear: both;
        width: 100%;
        display: block;
        content: "";
    }
    
    /* THIS WILL MAKE THE TRANSITION OVER CSS */
    
    /*
    This will throw all .item to the left at 50% relative to the container .vss-wrap
    */
    .vs-slider .item {
      transform: translate3d(-50%, 0, 0) scale(.7);
      z-index: 1;
      position: absolute;
      opacity: .2;
      transition: all 1s;
      top: 0;
      z-index: 1;
    }
    
    /*
    This will show and apply the transition only to the .active element
    */
    .vs-slider .item.active {
      transform: translate3d(0, 0, 0) scale(1);
      opacity: 1;
      z-index: 2;
      position: relative;
    }
    
    /*
    This will throw all elements set to the right of the .active element to 50% to the right and apply css styles
    */
    .vs-slider .item.active ~ .item {
      transform: translate3d(50%, 0, 0) scale(.7);
    }
    
    /* THIS WILL MAKE THE TRANSITION OVER CSS */
    
    .vss-nav {
        position: absolute;
        margin: 0;
        padding: 0;
        right: 5px;
        bottom: 0;
    }
    .vss-nav li {
        display: inline-block;
        color: #fff;
        margin: 0 5px;
        cursor: pointer;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div class="vs-slider">
    						<div class="vss-wrap">
    							<div class="item active"><img src="https://i.guim.co.uk/img/media/59dee3fae368b6625fcd588cdc0c759f6aacd117/0_0_6100_3660/500.jpg?quality=85&auto=format&fit=max&s=998f324a337c7c17be1d754e3b856201" alt="Slider Item" width="430" height="280"></div>
    							<div class="item"><img src="https://www.chileholidayarchitects.com/wp-content/uploads/2018/11/Chile-General-007-500x300.jpg" alt="Slider Item" width="430" height="280"></div>
    							<div class="item"><img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTDYTOz0c9d1h4Xj4HULfGeZVrQMw3zzA77vEPuX-RMY6ah8GkY" alt="Slider Item" width="430" height="280"></div>
    						</div>
    						<ul class="vss-nav">
    							<li class="prev">&lt;</li>
    							<li class="next">&gt;</li>
    						</ul>
    					</div>

    【讨论】:

    • 这是一个很好的解决方案,唯一的问题是动画效果已经改变,我不确定我是否可以实现我想要的以前的动画。您正在将动画应用于项目类并将它们的位置更改为绝对位置,而我希望 vss-wrap 移动,因此右侧的小图像也会有移动动画。我在这里创建了另一个问题,您可能想查看stackoverflow.com/questions/54167008/…
    • 如果你想滑动你的图片,你可以将样式应用到项目而不是包装上。我会检查问题
    • 我创建自定义滑块而不使用库的目的是因为我想要的动画我已经在我创建的小提琴上实现了,我对如何实现之前的动画有点迷茫我为您的示例创建,因为您已更改项目位置并将目标类更改为动画。如果您可以更新您的示例以具有与我的完全相同的动画,那真的很有帮助
    【解决方案2】:

    您可以通过索引使其变得简单。我不知道您为什么使用 299,因此将其视为 100 x 3,其中 100 是 1 的左移。

    请看下面的片段:

    ;( function($) {
        $(document).ready(function() {
            $('.vs-slider .item').each( function() {
                $(this).css('z-index', $('.vs-slider .item').length - $('.vs-slider .item').index(this));
            });
    
            $('.vss-nav').on('click', '.prev, .next', function() {
                var active = $(this).closest('.vs-slider').find('.item.active');
                var activeIndex = $('.vs-slider .item').index(active);
                
                var moveValue = 0;
                
                if ( $(this).hasClass('next') ) {
                	if(activeIndex+1== $('.vs-slider .item').length){
                    moveValue = 0;
    								$($('.vs-slider').find('.item').first()).addClass('active');
                  }else{
                  	moveValue = $('.vs-slider').find('.vss-wrap').position().left - ($('.vs-slider').find('.item').outerWidth() - 299);;
                    active.next().addClass('active');
                   ;
                  }
                }else{
                	if(activeIndex-1 == -1){
                  	moveValue = -($('.vs-slider .item').length * 100);
    								$($('.vs-slider').find('.item').last()).addClass('active');
                  }else{
                  	moveValue =  $('.vs-slider').find('.vss-wrap').position().left + ($('.vs-slider').find('.item').outerWidth() - 299);
                    active.prev().addClass('active');
                  }            
                }
                $('.vs-slider').find('.vss-wrap').css('transform', 'translate3d('+ moveValue +'px, 0px, 0px)');
                active.removeClass('active');
            });
            
        });
    })(jQuery);
    body {
      background: #222
    }
    .vs-slider {
      position: relative;
      overflow: hidden;    
      max-height: 290px;
      max-width: 500px;
    }
    .vs-slider img {
    	margin: 0;
    	vertical-align: top;
    }
    .vs-slider .vss-wrap {
    	min-width: 90VW;
    	transform: translate3d(0px, 0px, 0px);
    	transition: all 0.5s ease 0s;
    }
    .vs-slider .vss-wrap::after {
        clear: both;
        width: 100%;
        display: block;
        content: "";
    }
    .vs-slider .item {
    	float: left;
    	border: 1px solid #fff;
    	transform: scale(.7);
    	position: relative;
    	z-index: 1;
    	transition: all 1s ease 0s;
    	margin-right: -299px;
    }
    .vs-slider .item.active {
    	transform: scale(1);
    	z-index: 20 !important;
    }
    .vs-slider .item:not(.active) {
        z-index: 0;
        cursor: pointer;
    }
    .vss-nav {
        position: absolute;
        margin: 0;
        padding: 0;
        right: 5px;
        bottom: 0;
    }
    .vss-nav li {
        display: inline-block;
        color: #fff;
        margin: 0 5px;
        cursor: pointer;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div class="vs-slider">
    						<div class="vss-wrap">
    							<div class="item active"><img src="http://lorempixel.com/430/280/sports" alt="Slider Item" width="430" height="280"></div>
    							<div class="item"><img src="http://lorempixel.com/430/280/animals" alt="Slider Item" width="430" height="280"></div>
    							<div class="item"><img src="http://lorempixel.com/430/280/nature" alt="Slider Item" width="430" height="280"></div>
    						</div>
    						<ul class="vss-nav">
    							<li class="prev">&lt;</li>
    							<li class="next">&gt;</li>
    						</ul>
    					</div>

    你也可以测试一下here

    【讨论】:

    • 我对每个动画动作使用item.outerWidth() 值,因为margin-right 的值为-299,我从 itemOuterWidth 值中减去它,我不确定你从哪里得到100 值,但我认为如果项目宽度发生变化会产生问题。另外,我想我可能不清楚这个问题,我的主要问题是动画循环,我从这里创建了另一个问题stackoverflow.com/questions/54167008/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多