【问题标题】:How to detect when the scroll starts using Javascript/Jquery?如何检测滚动何时开始使用 Javascript/Jquery?
【发布时间】:2020-03-02 08:24:45
【问题描述】:

我想制作一个单页网站,不使用任何第三方库,例如 FullPage.js。

  • 当滚动开始时 --> 而不是等待自然滚动结束,我希望它不起作用(因此没有由鼠标引起的可见滚动)并运行我的代码。 (所以它总是可以转到下一部分或上一部分,而不依赖于用户滚动的数量)

你知道我怎样才能做到这一点吗?我的代码 sn-p 等待滚动结束,然后跳转到它应该的位置,所以它没有按预期工作。

(第一部分有一个“当前”类,然后代码 sn-p 通过添加/删除此类来操作 100vh 部分)

您可以在下面或此处查看我正在使用的代码 sn-p: https://codepen.io/makiwara/pen/PoqjdNZ

非常感谢您的帮助,祝您有美好的一天!

var script = document.createElement('script');script.src = "https://code.jquery.com/jquery-3.4.1.min.js";document.getElementsByTagName('head')[0].appendChild(script);
var timerId;
var scrollableElement = document.body; //document.getElementById('scrollableElement');

scrollableElement.addEventListener('wheel', checkScrollDirection);

function checkScrollDirection(event) {
    var $current = $('.current');
  if (checkScrollDirectionIsUp(event)) {
    console.log('UP');
$prev = $current.prev();

            if ($prev.length) {

                clearTimeout(timerId);
                timerId = setTimeout(function(){
                    $current.removeClass('current');
                    $prev.addClass('current');    
                    $('body,html').animate({
                        scrollTop: $('.current').offset().top
                    }, 100);         
                }, 100) 
            }




  } else {
    console.log('Down');
$next = $current.next();

            if ($next.length) {
                clearTimeout(timerId);
                timerId = setTimeout(function(){
                    $current.removeClass('current');
                    $next.addClass('current');
                    $('body,html').animate({
                        scrollTop: $('.current').offset().top
                    }, 100);         
               } , 100) 
            }

  }
}

function checkScrollDirectionIsUp(event) {
  if (event.wheelDelta) {
    return event.wheelDelta > 0;
  }
  return event.deltaY < 0;
}

【问题讨论】:

    标签: javascript jquery html scroll


    【解决方案1】:

    您需要限制事件监听器,即每个时间段仅限制一次函数调用。

    您的代码所做的实际上是去抖动,即仅在等待时间过后才限制函数调用。

    首先放弃您正在使用的计时器。您需要以某种方式阻止滚动多次发生。如果您使用Underscore.js's throttle function,JavaScript 部分可能会很简单,但有一个警告:它会在时间段过去后通过后续事件。幸运的是,它的去抖动方法接受了第三个参数,它给出了你想要的行为:

    scrollableElement.addEventListener(
      "wheel",
      _.debounce(checkScrollDirection, 200, true) // immediately call the function _once_
    );
    

    第三个参数使去抖动函数表现得像一个节流函数,即它只会触发一次,同时它会立即触发

    所以假设您的事件处理程序现在不受原始超时的影响

    function checkScrollDirection(event) {
      var $current = $(".current");
      if (checkScrollDirectionIsUp(event)) {
        console.log("UP");
        $prev = $current.prev("section");
        if ($prev.length) {
          $current.removeClass("current");
          $prev.addClass("current");
          $("body,html").animate(
            {
              scrollTop: $prev.offset().top
            },
            100
          );
        }
      } else {
        console.log("Down");
        $next = $current.next("section");
        if ($next.length) {
          $current.removeClass("current");
          $next.addClass("current");
          $("body,html").animate(
            {
              scrollTop: $next.offset().top
            },
            100
          );
        }
      }
    }
    

    顺便说一句,尝试养成在.next().prev() 中指定选择器的习惯,因为jQuery 将匹配所有可能的 兄弟姐妹,这很可能是你不想要的。在这种情况下,codepen 会附加额外的 &lt;script&gt; 元素,jQuery 也会匹配这些元素。

    现在如果你尝试这个,你会注意到窗口仍然响应每个滚动事件。滚动事件是无法取消的事件之一,因此您需要通过 CSS 禁用它

    最简单的方法是隐藏body的溢出

    body { max-height: 100vh; overflow: hidden; }
    

    就是这样。您可能需要调整油门等待时间以符合您的偏好。

    您可以在此处找到 Codepen 的工作版本:https://codepen.io/vassiliskrikonis/pen/XWbgxLj

    【讨论】:

    • 哇!!!你很棒!非常感谢您的帮助。它按预期工作,只是一件小事不是。如果我滚动“更大”,它通常会跳 2 或 3 节。有没有办法只跳 1 部分,无论我滚动多大?非常感谢,你让我开心!
    • 嗯,看看这个版本是否更适合你,所以我会相应地更新我的答案:codepen.io/vassiliskrikonis/pen/XWbgxLj
    • 是的,这正是我想要的! - 当我改变鼠标的位置并滚动到一个新的位置时,它就可以工作了 - 但是,如果我想在一个地方滚动页面,那么它不会识别新的滚动,除非我点击一次。它几乎就在那里,只是缺少了一点点。非常感谢您的帮助,您教会了我很多东西!
    • 很奇怪,它可以在我的 Mac 上运行。也许您在滚动之前等待的时间不够长?我已经更新了 codepen,您可以看到实际上滚动事件(取决于输入设备)可能会继续触发很长一段时间。老实说,要处理这种情况,最好使用专门的库。
    • 是的,没错!我还没等到滚动事件结束。那么一旦滚动事件开始就没有简单的方法来停止它吗?所以我们不应该等到它结束,它不是很舒服。你帮了我很多,我真的很抱歉我的评论,你可以跳过这个,如果我问的问题太多,这是我的最后一个。我将您的答案标记为解决方案,我真的很感激!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-10
    • 2013-01-25
    • 2012-04-07
    • 1970-01-01
    • 2013-08-04
    • 2012-02-27
    相关资源
    最近更新 更多