0

我在几个地方看到这个问题,但大多数要么给出解决方法,要么这个人的代码不能证明这一点。我并没有真正计划使用 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);});
         }
      }
   }
}

如果你将它复制并粘贴到 Chrome 控制台中,然后像这样运行它:scrollMore("#itemId"),窗口只会向下滚动大约 5 个像素,而它应该向下滚动 100 个像素。

取消注释console.log会显示它是这样运行的:像素0一次,像素1四次,2八次,3十六次,四次32次,五次37次;共 98 次。

我还在 if 中尝试了这种语法,它给了我相同的结果:

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

我意识到我可以使用以下代码按 ID 滚动到一个项目,但是我的项目在滚动时移动,所以它最终滚动到错误的位置。

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

所以问题是,当文档明确指出它在之后运行时,为什么 jQuery 在完成动画之前运行“完成”函数?当然,我能做些什么呢?

4

1 回答 1

3

几周前我遇到了类似的问题。当您尝试使用像$('html, body').animate();jQuery 这样的语法为多个元素设置动画时,实际上会分别为这两个元素触发动画函数。这意味着您添加的回调参数function(){scrollMore(id)}实际上被调用了两次。这意味着当动画完成时,它会在' 动画甚至完成html之前触发它的回调,然后一旦它完成它的事情,' 回调也会触发。我相信这就是那些多个意外控制台日志的来源。bodybody

有几种方法可以解决这个问题,但我想说最简单的方法是创建一个变量来告诉回调函数是否已被触发。就像是:

var animated = false;

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

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

       }
    }
);
于 2013-08-29T15:03:39.740 回答