JQuery滚动没有触发滚动

时间:2014-09-20 13:21:24

标签: javascript jquery

我使用以下javascript制作“粘性”导航,这使得当用户滚动浏览器时导航固定在屏幕顶部。此代码工作正常,但是当元素变为粘性并且元素的位置设置为“固定”时,主体中所有后续元素的位置“跳起来”以占据通过更改元素而创建的间隙相对于固定,并产生轻微的'颠簸'效果。为了解决这个问题,我尝试在将元素更改为固定时向滚动y位置添加偏移量,但这会通过再次触发滚动功能导致循环,并且页面会滚动到页面底部。

所以我的问题是 - 如何在下面的函数中为滚动位置添加偏移量?即,如何在$(窗口).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');
    }
});

非常感谢任何帮助

2 个答案:

答案 0 :(得分:3)

一般解决方案

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

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/

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

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

我认为在您的情况下,您可以通过虚拟元素更好地替换静态导航,该虚拟元素应与导航具有相同的高度。

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/

答案 1 :(得分:1)

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

// 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);期间)没有发生滚动事件,则不会在第一个滚动事件上调用处理程序。在这种情况下,在第一次事件中,假事件将被取消订阅,而原始事件将被重新订阅,但不会被调用。