【问题标题】:JQuery scroll without triggering on scrollJQuery滚动而不触发滚动
【发布时间】:2014-09-20 13:21:24
【问题描述】:

我使用以下 javascript 制作了一个“粘性”导航,当用户滚动过去时,它使导航固定在屏幕顶部。这段代码工作正常,虽然当元素被设置为粘性并且元素的位置设置为“固定”时,主体中所有以下元素的位置“跳跃”以占据从更改元素产生的间隙相对于固定,并产生轻微的“颠簸”效果。为了解决这个问题,我尝试在元素更改为固定时向滚动 y 位置添加偏移量,但这会通过再次触发滚动功能导致循环,并且页面滚动到页面底部。

所以我的问题是 - 如何在下面的函数中为滚动位置添加偏移量?即,如何在 $(window).scroll 函数中设置滚动位置,而不 触发 $(window).scroll 函数进入循环?

 $(window).scroll(function (event) {

    var y = $(this).scrollTop();

    var top = $('#main-navigation').offset().top;

    if (y >= top) {
        $('#navigation').addClass('fixed');
    }
    else {
        $('#navigation').removeClass('fixed');
    }
});

非常感谢任何帮助

【问题讨论】:

  • 可以添加event.preventDefault()来停止执行window的默认滚动行为。另外,你能发一个Fiddle 让我们可以看到这个问题吗?

标签: javascript jquery


【解决方案1】:

一般解决方案

这是防止循环的一般解决方案:

var lastScrollTop = 0;
var defaultScrollHandler = function(e)
{
    var y = $(this).scrollTop();

    //change event handlers    
    $(window).off("scroll", defaultScrollHandler);
    $(window).on("scroll", tmpScrollHandler);

    var jumpHeight = 200;

    if(lastScrollTop > y)
        jumpHeight *= -1;

    var newY = y + jumpHeight;

    $(window).scrollTop(y + jumpHeight);
};

var tmpScrollHandler = function()
{
    lastScrollTop = $(this).scrollTop();

    //change event handlers back
    $(window).off("scroll", tmpScrollHandler);
    $(window).on("scroll", defaultScrollHandler);
};

$(window).on("scroll", defaultScrollHandler);

http://jsfiddle.net/udcwgyub/

在设置新的滚动位置之前,您可以禁用当前事件处理程序并为滚动事件注册另一个处理程序。设置新的滚动位置后,将调用另一个处理程序。此处理程序将自行禁用并再次注册实际的处理程序。

为您的案例提供更好的解决方案

我认为在您的情况下,您最好用一个与导航高度相同的虚拟元素替换静态导航。

var navOffset = $("nav").offset().top;

$("#dummyNav").height($("nav").innerHeight());

$(window).scroll(function(){

    var y = $(this).scrollTop();

    var $nav = $("nav");
    var $dummyNav = $("#dummyNav");

    if(y >= navOffset)
    {
        if(!$nav.hasClass("fixed"))
        {
            $nav.addClass("fixed");
            $dummyNav.show();
        }
    }
    else if($nav.hasClass("fixed"))
    {
        $nav.removeClass("fixed");
        $dummyNav.hide();
    }

});

http://jsfiddle.net/wdup394c/

【讨论】:

    【解决方案2】:

    最简单的解决方案是临时替换滚动事件订阅。

    // initial subscribe to scroll event
    this.$el.on("scroll", this.handleScroll);
    
    // unsubscribe initial handler and subscribe fake handler before manual scroll
    this.$el.off("scroll");
    this.$el.on("scroll", () =>
    {
        this.$el.off("scroll");
        this.$el.on("scroll", this.handleScroll);
    });
    
    // scroll manually
    this.$el.scrollTop(0);
    

    但是,如果在手动滚动期间(this.$el.scrollTop(0); 期间)没有发生滚动事件,则不会在第一次滚动事件时调用处理程序。在这种情况下,在第一个事件期间,假事件将被取消订阅,原始事件被重新订阅,但不会被调用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-22
      • 2018-04-16
      • 1970-01-01
      • 1970-01-01
      • 2012-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多