animate()在滚动停止之前不会触发

时间:2015-09-01 16:29:07

标签: jquery css scroll jquery-animate

目标:

我希望我的固定标题元素在用户向下滚动时从屏幕上滑动(有效隐藏),并在用户向上滚动时向下移动。

问题:

实际的动画和逻辑工作正常,但动画不会在用户停止滚动之前开始,而不是在滚动仍然像它应该的那样开始时开始。

这是在Chrome和Firefox上复制的。但是,使用完全相同的代码,解决方案似乎在JSFiddle中正常工作:

https://jsfiddle.net/8cj7v6n5/

使用Javascript:

var lastScroll = 0;
var scrollDelta = 10;
var animating = false;

$(window).on('scroll', function() {
    //if animation isn't currently taking place, begin animation
    if (!animating) hasScrolled();
});

function hasScrolled() {
    var st = $(window).scrollTop();

    //if user hasn't scrolled past scrollDelta, do not animate yet
    if(Math.abs(lastScroll - st) <= scrollDelta)
        return;

    animating = true;

    if (st > lastScroll && st >= 0){    // Scroll Down
        $('header').animate( { top: -80 }, { queue: false, duration: 500, complete: function() { animating = false; } });
    }
    else {  // Scroll Up
        $('header').animate( { top: 0 }, { queue: false, duration: 500, complete: function() { animating = false } });
    }
    lastScroll = st;
}

2 个答案:

答案 0 :(得分:2)

您可以对动画进行排队,并使用stop()和animate()来运行队列中的最后一个动画,而不是使用动画标记。

编辑:你可以使用方向标志来检测滚动方向是否有变化。

JavaScript的:

var lastScroll = 0;
var scrollDelta = 10;
var animationDirection = 0; // 0 for up direction, 1 for down direction

$(window).on('scroll', function () {
    hasScrolled();
});

function hasScrolled() {
    var st = $(window).scrollTop();
    if (Math.abs(lastScroll - st) <= scrollDelta)
        return;

    if (st > lastScroll && st >= 0 && animationDirection == 0) {    // Scroll Down                                    
        $('header').stop().animate({ top: -80 }, 500);
        animationDirection = 1;
    }
    else if (st <= lastScroll && st >= 0 && animationDirection == 1) {  // Scroll Up
        animationDirection = 0;
        $('header').stop().animate({ top: 0 }, 500);
    }
    lastScroll = st;
}

JSFiddle:https://jsfiddle.net/8cj7v6n5/27/

答案 1 :(得分:1)

问题是,只有在动画发生时才会更新用于lastscroll的值。它应该总是更新,因为您可以在动画运行时滚动屏幕并且lastscroll值将不同于真实的顶部滚动值,然后再次比较这些值,系统认为是高于或低于实际值。

示例:

  1. 窗口scrolltop为0您向下滚动 - &gt;第一部动画 火灾,此时窗口的滚动顶部是100,它被分配给 变量st。
  2. 您继续向下滚动 - &gt;国旗是开的,动画呢 不火,此时窗口的滚动顶部是200,但事实并非如此 asigned。
  3. 第一个动画结束 - &gt; st被分配给lastscroll(100)
  4. 你向上滚动的下一个动作,lastscroll是100,真正的滚动顶部是 实际上是200.新的滚动顶部是190但是当你与lastscroll相比时,系统认为你正在向下滚动。
  5. 这是更正后的代码:

    var lastScroll = 0;
    var scrollDelta = 10;
    var animating = false;
    
    $(window).on('scroll', function() {
        //if animation isn't currently taking place, begin animation
        if (!animating) {hasScrolled()}else{lastScroll = $(window).scrollTop();};
    });
    
    function hasScrolled() {
        var st = $(window).scrollTop();
    
        //if user hasn't scrolled past scrollDelta, do not animate yet
        if(Math.abs(lastScroll - st) <= scrollDelta)
            return;
    
        animating = true;
    
        if (st > lastScroll && st >= 0){    // Scroll Down
            $('header').animate( { top: -80 }, { queue: false, duration: 500, complete: function() { animating = false; } });
        }
        else {  // Scroll Up
            $('header').animate( { top: 0 }, { queue: false, duration: 500, complete: function() { animating = false } });
        }
        lastScroll = st;
    }
    

    这是我用控制台日志调试的小提琴: https://jsfiddle.net/8cj7v6n5/18/

    修改 这段代码适用于我的小提琴,尝试它,如果它的工作,那么问题是在页面的另一个组件,这里没有发布。 也许它是另一行代码或库,它覆盖了.animate()或scroll事件的行为。

    <html>
      <head>
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
      <script type="text/javascript" charset="utf-8">
    var lastScroll = 0;
    var scrollDelta = 10;
    var animating = false;
    
    var lastScroll = 0;
    var scrollDelta = 10;
    var animating = false;
    
    $(window).on('scroll', function() {
        //if animation isn't currently taking place, begin animation
        if (!animating) {hasScrolled()}else{lastScroll = $(window).scrollTop();};
    });
    
    function hasScrolled() {
        var st = $(window).scrollTop();
    
        //if user hasn't scrolled past scrollDelta, do not animate yet
        if(Math.abs(lastScroll - st) <= scrollDelta)
            return;
    
        animating = true;
    
        if (st > lastScroll && st >= 0){    // Scroll Down
            $('header').animate( { top: -80 }, { queue: false, duration: 500, complete: function() { animating = false; } });
        }
        else {  // Scroll Up
            $('header').animate( { top: 0 }, { queue: false, duration: 500, complete: function() { animating = false } });
        }
        lastScroll = st;
    }
      </script>
      <style type="text/css">
      body {
        height: 2000px;
        width: 100%;
        background-image: url(http://static.tumblr.com/cc2l8yc/qa8nbkd68/2.jpg);
        background-repeat: repeat;
      }
    
      header {
          height: 80px;
          width: 100%;
          background-color: red;
          position: fixed;
          top: 0;
          left: 0;
      }
      </style>
      </head>
      <body>
        <header></header>
      </body>
    </html>