简体   繁体   English

为什么jQuery的.animate()在完成动画之前运行“ complete”功能?

[英]Why does jQuery's .animate() run the “complete” function before it completes the animation?

I'm seeing this asked several places but most either give a work-around or the person's code doesn't prove the point. 我在几个地方都看到了这个问题,但是大多数都给出了解决方法,或者该人的代码无法证明这一点。 I'm not really planning on scrolling down every pixel at 1 milisecond per pixel using jQuery .annimate(), but just to demonstrate the problem, here's my code: 我并不是真正打算使用jQuery .annimate()以每像素1毫秒的速度向下滚动每个像素,但是为了演示这个问题,这是我的代码:

window.stopscrolling = 0;

function scrollMore(id) {
   stopscrolling++;
   if (stopscrolling < 100) {
      var y = $(window).scrollTop();
      if ($("#"+id).offset().top != y){
         //console.log(y);
         if ($("#"+id).offset().top > y) {
             $('html, body').animate({
                scrollTop: y+1
             }, 1, "linear", function(){scrollMore(id);});
         }
         else {
             $('html, body').animate({
                scrollTop: y-1
             }, 1, "linear", function(){scrollMore(id);});
         }
      }
   }
}

If you copy and paste it into the Chrome console, and run it like so: scrollMore("#itemId"), the window will only scroll down about 5 pixel, whilst it should scroll down 100. 如果将其复制并粘贴到Chrome控制台中,然后按以下方式运行它:scrollMore(“#itemId”),则该窗口只会向下滚动5个像素,而向下滚动100个像素。

Uncommenting the console.log will reveal that it runs through like this: pixel 0 once, pixel 1 four times, 2 eight times, 3 sixteen times, four 32 times, five 37 times; 取消对console.log的注释,它会像这样运行:像素0一次,像素1四个,像素2八次,像素3十六次,像素四次32,像素五十七次; totaling 98 times. 共98次。

I also tried with this syntax in the if, and it gave me the same results: 我还在if中尝试了这种语法,它给了我相同的结果:

if ($("#"+id).offset().top > y) {
     $('html, body').animate({
        scrollTop: y+1
     },
     {
        duration : 1,
        easing: "linear",
        complete: function(){scrollMore(id)}
    });
 } 

I realise that I can use the following code to scroll to an item by ID, but my item moves on scroll, so it ends up scrolling to the wrong place. 我意识到我可以使用以下代码按ID滚动到某个项目,但是我的项目在滚动时移动,因此最终滚动到错误的位置。

$('html, body').animate({
    scrollTop: $("#"+id).offset().top
    }, 2000);

So the question is, Why does jQuery run the "complete" function BEFORE it completes the animation when the documentation explicitly states that it runs after? 因此,问题是,当文档明确声明要在其之后运行时,为什么jQuery在其完成动画之前运行“完成”功能? And, of course, what can I do about it? 而且,当然,我该怎么办?

I ran into a similar problem a few weeks ago. 几周前,我遇到了类似的问题。 When you try to animate multiple elements using syntax like $('html, body').animate(); 当您尝试使用$('html, body').animate();等语法为多个元素$('html, body').animate(); jQuery actually fires the animate function for both elements separately. jQuery实际上为两个元素分别触发了动画功能。 Meaning that the callback parameter you added, function(){scrollMore(id)} , is actually called twice. 意味着您添加的回调参数function(){scrollMore(id)}实际上被调用了两次。 That means when html is done animating it'll fire off it's callback before the body 's animation is even finished and then the body 's callback will fire as well once it's done its thing. 这意味着当html完成动画设置时,它将在body动画结束之前触发它的回调,然后一旦完成它的动作, body的回调也会触发。 I believe that's where those multiple unexpected console logs are coming from. 我相信这就是那些多个意外控制台日志的来源。

There's several ways to get around this but I'd say the easiest is to create a variable that tells the callbacks whether one has been fired or not. 有几种方法可以解决此问题,但是我想说,最简单的方法是创建一个变量,该变量告诉回调函数是否被触发。 Something like: 就像是:

var animated = false;

$('html, body').animate({
       scrollTop: y+1
    },
    {
       duration : 1,
       easing: "linear",
       complete: function(){

          if (!animated) {
              animated = true;
              scrollMore(id);
          }

       }
    }
);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM