【问题标题】:jQuery scroll function fire once when element becomes visiblejQuery滚动功能在元素变得可见时触发一次
【发布时间】:2016-09-11 10:57:17
【问题描述】:

大家好,我在这个脚本上使用了滚动功能,但每次用户滚动时它都会触发。我希望它只在用户向下滚动到#ror 时触发一次。我尝试使用fired 变量来检查它是否已被触发,但这似乎不起作用。我知道有些人之前已经回答过这个问题,但这是我从中获得解雇解决方案的地方,并且只能让它工作一次。有人认为他们可以帮忙吗?

$( window  ).scroll(function() {
var fired = 0;
    console.log(fired);
    if(fired == 0){
    $('#ror').html('');
    $('#ror').goalProgress({
     goalAmount: 100,
     currentAmount: 75,
     textBefore: 'progress bar',
     textAfter: '',
     offset: 10,
     });
     fired=1;   
   }
});

【问题讨论】:

    标签: javascript jquery html scroll onscroll


    【解决方案1】:
    $(window).scroll(function(event) {
        var eT = $('#ror').offset().top,
        wH = $(this).height(),
        wSt = $(this).scrollTop();
        if(wSt > (eT-wH)) {
          alert('you have scrolled to the ror!');
          //detach scroll event handler, as we dont want it to fire again
          $(this).off(event);
        }
    }
    

    上面的代码检查用户是否向下滚动到一个元素。如果是,请发出警报并分离window 的滚动事件处理程序。可以参考jquery documentation查看offset、height和scrollTop的含义。

    现在,正如 @Pevera 指出的那样,将事件处理程序附加到窗口滚动的成本很高,您应该意识到这一点。如果您在滚动回调中有一些繁重的代码执行,它将妨碍滚动页面。因此,如果您必须将处理程序附加到窗口滚动,请在超时回调中运行滚动回调代码。它确保在一定延迟后运行滚动回调代码,这有助于更好地滚动页面。用超时重写上面的代码将如下所示:

    var timeout = null;
    $(window).scroll(function (event) {
        if (!timeout) {
            // set a timeout to run after 250ms
            timeout = setTimeout(function () {
                clearTimeout(timeout);
                timeout = null;
                var eT = $('#ror').offset().top,
                wH = $(this).height(),
                wSt = $(this).scrollTop();
                if (wSt > (eT-wH)){
                  alert('you have scrolled to the ror!');
                  //detach scroll event handler, as we dont want it to fire again
                  $(this).off(event);
                }
            }, 250);
        }
    });
    

    每次用户滚动页面时,超时设置为在(至少)250 毫秒后运行。在超时回调中,我们删除了这个超时处理程序并检查用户是否已经滚动到元素。如果是,我们会发出警报并分离窗口的滚动处理程序,以便它不会再次运行。

    请参阅此FIDDLE 以获得更好的理解。

    有关此 stackoverflow post 和 John Resig 的 blog post 的更多信息。

    【讨论】:

      【解决方案2】:

      要检测给定#target 何时滚动到视图中,您可以查看它的顶部位置,并检查该位置是否已经在视口内。

      $('#target').offset().top - $(window).outerHeight() > $(window).scrollTop();
      

      等式的左边部分是不变的(只要你不移动任何东西,或者改变视口的大小)。因此,将它移到事件处理函数之外可能是明智的。您需要记住,滚动事件相当昂贵,因为它会在您滚动时不断触发,并且浏览器已经很忙于渲染视口。

      工作完成后,您可以删除事件处理程序。

      $(window).off(event);
      

      所以你的最终代码看起来像这样:

      var triggerAtY = $('#target').offset().top - $(window).outerHeight();
      
      $(window).scroll(function(event) {
        // #target not yet in view
        if (triggerAtY > $(window).scrollTop()) {
          return;
        }
      
        // run your task
      
        // remove this event handler
        $(this).off(event);
      }); 
      

      看看演示:https://jsfiddle.net/6whnfa02/1/

      文档:

      【讨论】:

      • 这两种方式都不起作用,正如我在上面的评论中提到的那样,当我检查控制台日志时,我看到 0 但是一旦我开始滚动,我就会看到 1 被解雇。我希望它只在我到达 id 一次时加载。
      • sry @Mohammed,我似乎误读了你的问题(我冒昧地改写了它,因为我显然不是唯一一个)。我已经更新了我的答案!
      【解决方案3】:

      您需要将触发的变量移到滚动函数之外。 正如您现在所做的那样,您正在重新初始化 fired 变量,并在每次触发滚动事件时将其设置为 0

      var fired = 0;
      $(window).scroll(function() {
          console.log(fired);
          if(fired == 0){
          $('#ror').html('');
          $('#ror').goalProgress({
           goalAmount: 100,
           currentAmount: 75,
           textBefore: 'progress bar',
           textAfter: '',
           offset: 10,
           });
           fired=1;   
         }
      });
      

      【讨论】:

      • 我这样做了,但它没有用,我在控制台上检查了,当我点击滚动时,0 变成了 1。我试图让它只在滚动条到达它时触发一次,因为它就在页面的底部,你跟着我吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-27
      • 1970-01-01
      • 2013-10-01
      • 2016-04-21
      • 2011-08-20
      • 1970-01-01
      • 2019-03-22
      相关资源
      最近更新 更多