用 Animate.css + jQuery 制作的滑块在重复时跳到最后一步

Slider made with Animate.css + jQuery jumping last step when repeating

我在一个网站上工作,该网站有一个类似于测验的部分,我使用 animate.css 实现了一个简单的滑块效果jquery 通过步骤导航,问题是在测验中,当用户到达 "slider" 的最后一项(即结果)时,有一个按钮他可以重新开始,但在我的代码中,当你点击重复按钮时,当你再次到达最后一步时,它会再次跳转到第一步,就像你点击了重复按钮一样。

我写了一个片段,您可以在其中看到问题,要重现它,您需要:

  1. 单击 "next" 直到到达最后一项,在本例中为第四项
  2. 单击 "back to start" 按钮
  3. 再点下一步,你会看到当你点到第三个的时候,如果你点"next"去到第四个,它就到第四个,然后又淡到第一个,如如果您点击了 "back to start" 按钮

var animationEnd = 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend';
$.fn.extend({
 animateCss: function(animationName) {
  this.addClass('animated ' + animationName).one(animationEnd, function() {
   $(this).removeClass('animated ' + animationName);
  });
 }
});

$('.btn:not(.-back)').click(function(){
 var $currentItem = $(this).closest('.item');
  var nextItemNumber = $currentItem.data('item') + 1;
  var $nextItem = $('.item[data-item="'+nextItemNumber+'"]');
  $currentItem.animateCss('fadeOutLeft');
  $currentItem.one(animationEnd, function(){
   $currentItem.removeClass('-active');
    $nextItem.addClass('-active');
    $nextItem.animateCss('fadeInRight');
  })
})
$('.btn.-back').click(function(){
 var $currentItem = $(this).closest('.item');
  var nextItemNumber = 1;
  var $nextItem = $('.item[data-item="'+nextItemNumber+'"]');
  $currentItem.animateCss('fadeOut');
  $currentItem.on(animationEnd, function(){
   $currentItem.removeClass('-active');
    $nextItem.addClass('-active');
    $nextItem.animateCss('fadeIn');
  })
})
.slider-list {
  padding: 25px;
  overflow: hidden;
}
.slider-list > .item {
  animation-duration: .6s;
  display: none;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  background-color: teal;
  padding: 50px 120px;
}
.slider-list > .item.-active {
  display: flex;
}
.slider-list > .item > .content {
  color: #fff;
  font-family: 'Arial', sans-serif;
  font-size: 55px;
  margin-bottom: 18px;
}
.slider-list > .item > .btn {
  padding: 12px 18px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="slider-list">
  <li class="item -active" data-item="1">
    <div class="content">
      1
    </div>
    <button type="button" class="btn">
      NEXT
    </button>
  </li>
  <li class="item" data-item="2">
    <div class="content">
      2
    </div>
    <button type="button" class="btn">
      NEXT
    </button>
  </li>
  <li class="item" data-item="3">
    <div class="content">
      3
    </div>
    <button type="button" class="btn">
      NEXT
    </button>
  </li>
  <li class="item" data-item="4">
    <div class="content">
      4
    </div>
    <button type="button" class="btn -back">
      BACK TO START
    </button>
  </li>
</ul>

我好像找不到问题出在哪里,为什么重复这个过程时,会触发返回开始按钮

问题是您的后退按钮事件处理程序,您使用 on() 而不是 one() 来附加 animationEnd 的事件处理程序,有效地多次添加该处理程序。

$currentItem.one(animationEnd, function(){
    $currentItem.removeClass('-active');
    $nextItem.addClass('-active');
    $nextItem.animateCss('fadeInRight');
  })

将其更改为 .one() 将修复它:

var animationEnd = 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend';
$.fn.extend({
 animateCss: function(animationName) {
  this.addClass('animated ' + animationName).one(animationEnd, function() {
   $(this).removeClass('animated ' + animationName);
  });
 }
});

$('.btn:not(.-back)').click(function(){ 
 var $currentItem = $(this).closest('.item');
  var nextItemNumber = $currentItem.data('item') + 1;
  var $nextItem = $('.item[data-item="'+nextItemNumber+'"]');
  $currentItem.animateCss('fadeOutLeft');
  $currentItem.one(animationEnd, function(){
   $currentItem.removeClass('-active');
    $nextItem.addClass('-active');
    $nextItem.animateCss('fadeInRight');
  })
})
$('.btn.-back').click(function(){
 var $currentItem = $(this).closest('.item');
  var nextItemNumber = 1;
  var $nextItem = $('.item[data-item="'+nextItemNumber+'"]');
  $currentItem.animateCss('fadeOut');
  $currentItem.one(animationEnd, function(){
   $currentItem.removeClass('-active');
    $nextItem.addClass('-active');
    $nextItem.animateCss('fadeIn');
  })
})
.slider-list {
  padding: 25px;
  overflow: hidden;
}
.slider-list > .item {
  animation-duration: .6s;
  display: none;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  background-color: teal;
  padding: 50px 120px;
}
.slider-list > .item.-active {
  display: flex;
}
.slider-list > .item > .content {
  color: #fff;
  font-family: 'Arial', sans-serif;
  font-size: 55px;
  margin-bottom: 18px;
}
.slider-list > .item > .btn {
  padding: 12px 18px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="slider-list">
  <li class="item -active" data-item="1">
    <div class="content">
      1
    </div>
    <button type="button" class="btn">
      NEXT
    </button>
  </li>
  <li class="item" data-item="2">
    <div class="content">
      2
    </div>
    <button type="button" class="btn">
      NEXT
    </button>
  </li>
  <li class="item" data-item="3">
    <div class="content">
      3
    </div>
    <button type="button" class="btn">
      NEXT
    </button>
  </li>
  <li class="item" data-item="4">
    <div class="content">
      4
    </div>
    <button type="button" class="btn -back">
      BACK TO START
    </button>
  </li>
</ul>

但是一种更简单的方法可能是使用当前幻灯片本身的索引来指示下一张幻灯片,如下所示:

var animationEnd = 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend';
$.fn.extend({
    animateCss: function(animationName) {
        this.addClass('animated ' + animationName).one(animationEnd, function() {
            $(this).removeClass('animated ' + animationName);
        });
    }
});

$('.slider-list .btn').click(function(){
    var $this=$(this);
    var $items=$this.closest('.slider-list').find('.item');
    var $currentItem = $this.closest('.item');
    var nextItemNumber = $items.index($currentItem)+1;
    nextItemNumber = nextItemNumber >= $items.length ? 0 : nextItemNumber;
    var $nextItem = $items.eq(nextItemNumber);

    $currentItem.animateCss('fadeOutLeft');
    $currentItem.one(animationEnd, function(){
        $currentItem.removeClass('-active');
        $nextItem.addClass('-active');
        $nextItem.animateCss('fadeInRight');
    })
});
.slider-list {
  padding: 25px;
  overflow: hidden;
}
.slider-list > .item {
  animation-duration: .6s;
  display: none;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  background-color: teal;
  padding: 50px 120px;
}
.slider-list > .item.-active {
  display: flex;
}
.slider-list > .item > .content {
  color: #fff;
  font-family: 'Arial', sans-serif;
  font-size: 55px;
  margin-bottom: 18px;
}
.slider-list > .item > .btn {
  padding: 12px 18px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="slider-list">
  <li class="item -active" data-item="1">
    <div class="content">
      1
    </div>
    <button type="button" class="btn">
      NEXT
    </button>
  </li>
  <li class="item" data-item="2">
    <div class="content">
      2
    </div>
    <button type="button" class="btn">
      NEXT
    </button>
  </li>
  <li class="item" data-item="3">
    <div class="content">
      3
    </div>
    <button type="button" class="btn">
      NEXT
    </button>
  </li>
  <li class="item" data-item="4">
    <div class="content">
      4
    </div>
    <button type="button" class="btn -back">
      BACK TO START
    </button>
  </li>
</ul>