jQuery animate()的完整函数在完成之前触发

时间:2017-06-25 18:32:23

标签: jquery

将页面滚动到某个元素后,我需要为该元素添加一个类。问题是,错误的元素获取类,因为完成的函数在完成滚动动画之前触发。我知道因为如果我将完整的函数包装在setTimeout()中就可以了。

为什么完成功能会在完成之前触发?这是一个已知的问题吗?什么是解决这个问题最可靠的方法?

我的代码:

$('html, body').animate({
  scrollTop: current_element_position + 'px'
}, 'fast', function(){
  current_element.addClass('current_element');
}); 

4 个答案:

答案 0 :(得分:2)

您正在对2个元素调用动画效果:htmlbody。这意味着动画实际上运行了两次,完整的函数也会被调用两次。

通常这样做的原因是某些浏览器仅支持滚动html而其他浏览器仅支持滚动body。这个选择器将同时作为目标,解决了这个问题,但也会导致这个双动画调用。

实际滚动的动画完成得更快,因此在完成另一个元素上的真实动画之前触发完整的调用。

知道这一点你可以通过设置一个额外的变量来解决它,所以你的代码只能在最后一次调用时执行。

var isComplete = false;
$('html, body').animate({
  scrollTop: current_element_position + 'px'
}, 'fast', function() {
  if (isComplete) {
    current_element.addClass('current_element');
    isComplete = false;
  }
  else {
    isComplete = true;
  }
});

甚至更简单,使用承诺。

$('html, body')
  .animate({ scrollTop: current_element_position + 'px' }, 'fast')
  .promise()
  .then(function() {
    current_element.addClass('current_element');
  });

答案 1 :(得分:0)

我不知道您的HTML是怎样的。尽管如此,我希望我有了你的意图并尝试了另一种没有jQuery和动画的方法。它基本上检查页面滚动时元素的顶部是否在特定范围内。也许它有帮助...

var divs = document.querySelectorAll('.testdiv');
window.onscroll = function() {
  divs.forEach(function(item) {
    var top = item.getBoundingClientRect().top;
    item.style.background = 'transparent';
    if (top >= 70 && top <= 140) {
      item.style.background = 'red';
    }
  });
}
.testdiv{
  width: 200px;
  height: 70px;
  border: 1px solid black;
}
.testdiv:first-of-type{
  margin-top: 100px;
}
<div class="testdiv"></div>
<div class="testdiv"></div>
<div class="testdiv"></div>
<div class="testdiv"></div>
<div class="testdiv"></div>
<div class="testdiv"></div>
<div class="testdiv"></div>
<div class="testdiv"></div>
<div class="testdiv"></div>
<div class="testdiv"></div>
<div class="testdiv"></div>
<div class="testdiv"></div>
<div class="testdiv"></div>
<div class="testdiv"></div>
<div class="testdiv"></div>
<div class="testdiv"></div>
<div class="testdiv"></div>

答案 2 :(得分:0)

如果您打算在滚动到视图中的元素时添加Class,请尝试以下代码。

$(function() {
  /**
	jQuery Custom method to find if element is in View
*/
  $.fn.isInView = function() {
    if (!this.length) return false;
    var rect = this.get(0).getBoundingClientRect();
    return (
      rect.top >= 0 &&
      rect.left >= 0 &&
      rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
      rect.right <= (window.innerWidth || document.documentElement.clientWidth)
    );

  };
  /**
	Window Scroll Event:
*/
  $(window).on('scroll', function(e) {
    var $this = $(this);
    /**
        Trigger Custom Event on timeout if Scroll is stopped else clear the timeout
      */
    clearTimeout($this.data('scrollTimeout'));
    $this.data('scrollTimeout', setTimeout(function() {
      $(window).trigger('scrollStop')
    }, 50, e));
  });

  /**
         On ScrollStop Loop Through Each Element and check if it is in view, If yes add Class else remove Class
        */
  $(window).on('scrollStop', function(ev) {
    $('div').each(function() {
      var $div = $(this)
      if ($div.isInView()) {
        $div.addClass('color');
      } else {
        $div.removeClass('color');
      }
    });
  }).trigger('scrollStop');
});
div {
  width: 100%;
  height: 170px;
  border: 1px solid black;
}

.color {
  background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>

答案 3 :(得分:0)

**您可以使用窗口滚动属性** 试试这个它应该工作。当你滚动到div然后添加类,当你再次移动到顶部然后类删除。 你可以在这里查看https://jsfiddle.net/surendra786/qnhw5ov7/

html --
<p class="new"></div>

 script ---

$('document').ready(function(){
  var current_element=$('.new');
  var current_element_position = $('.new').position().top;

  $(window).scroll(function() {    
  var scroll = $(window).scrollTop(); 
  current_element.toggleClass('current_element',
  scroll >= current_element_position
  );

  });
 });