jQuery/JavaScript:检测滚动方向 - 代码结构问题

12
我需要检测用户滚动的方向 - “向上”还是“向下”。基于这个答案中找到的代码:如何确定jQuery滚动事件的方向?,我尝试将其包装在一个函数中,使其更具区分性 - 但不幸的是,它没有起作用。我认为这与我返回值的方式有关,但方向始终是“向上”。由于我对JavaScript还比较新,我无法解决这个问题。
以下是代码:
$(document).ready(function () {

    'use strict';

    var lastScrollTop = 0,
        st,
        direction;

    function detectDirection() {

        st = window.pageYOffset;

        if (st > lastScrollTop) {
            direction = "down";
        } else {
            direction = "up";
        }

        lastScrollTop = st;

        return  direction;

    }

    $(window).bind('scroll', function() {

        detectDirection();
        console.log(detectDirection());

    });

});

我还设置了一个Fiddle

你能帮我找出问题在哪里吗?


我建议将函数和变量声明移到ready函数之外。我不确定这是否能解决问题,但值得一试。 - Adam Plocher
@AdamPlocher 感谢你的建议,但没有帮助。不过,这样做是否有一般性的好处呢?也许在性能方面? - Sven
4个回答

6
$(window).bind('scroll', function() {

    var dir = detectDirection();
    console.log(dir);

});

在每次滚动事件中,你调用了两次detectDirection()。第一次检测到了正确的方向,但第二次仍然在同一位置看到它,所以返回了“上”,这就是你记录的内容。

2

原始代码无法正常工作,因为我们从未更新lastScrollTop,这是可行的代码...

$(function(config){
    var lastScrollTop = 0, // setting initial scrolltop as top of page
        direction; // direction of scroll 1)up -1)down 0)static

    function detectDirection() {
        // current scrollTop can't be cached or in the local global scope
        var st = window.pageYOffset;

        if (st > lastScrollTop) {
            // scrolling down
            direction = -1;
        } else if (st < lastScrollTop ){
            // scrolling up
            direction = 1;
        } else {
            // static
            direction = 0;
        }

        // updated lastscrolltop with new current top
        lastScrollTop = st;

        // return the direction
        return direction;
    }`

我使用0表示静态/1表示向上滚动/-1表示向下滚动。

希望这对某些人有所帮助。


2

看看这样做能得到什么:

if (st > lastScrollTop) {
    direction = "down";
} else if (st < lastScrollTop ){
    direction = "up";
} else {
    direction = "static";
}

除了Barmar所说的,您可以删除控制台输出上面的那行代码(调用),只保留以下内容:
console.log(detectDirection());

1
是的,你完全正确。我只是没有意识到 console.log(detectDirection()); 实际上也会调用该函数,尽管这实际上很清楚。 - Sven
1
如果这是你唯一的JS错误,那么你会没事的 ;) - vol7ron

1

我提供了一个新的答案,因为虽然BarMar的答案解决了您的直接问题,但该解决方案无法帮助您以使您能够完成两件事情的方式来构建代码结构。

  1. Scope the scroll object more broadly, allowing you to access its attributes elsewhere. This would allow you to do something if the scroll position is a certain value.

  2. Improve the performance of the scrolling.

    // Your current functionality
    $(document).ready(function() {
      var scroll = {
        down: true,
        pos: 0
      };
      var scrollPos;
    
      var detectDirection = function() {
        scrollPos = window.pageYOffset;
    
        if (scrollPos > scroll.pos) {
          scroll.down = true;
        } else {
          scroll.down = false;
        }
    
        scroll.pos = scrollPos;
      };
    
      $(window).on('optimizedScroll', function() {
        detectDirection();
    
        // Do something based on scroll direction
        if (scroll.down == true) {
          // fooFunction();
        } else {
          // barFunction();
        }
    
        // Do something based on scroll position,
        // where scrollTrigger is a number
        if (scroll.pos > scrollTrigger) {
          // bazFunction();
        }
      });
    });
    
    // Improve scroll performance
    (function() {
        var throttle = function(type, name, obj) {
          var obj = obj || window;
          var running = false;
          var func = function() {
            if (running) {
              return;
            }
            running = true;
            requestAnimationFrame(function() {
            obj.dispatchEvent(new CustomEvent(name));
              running = false;
            });
          };
          obj.addEventListener(type, func);
        };
    
        throttle('scroll', 'optimizedScroll');
    })();
    

与其使用 .bind(),你应该使用 .on(),根据 jQuery .bind() 文档

立即调用函数表达式 (IIFE) 来提高滚动性能,来自于 MDN 滚动事件文档


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接