我使用以下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');
}
});
非常感谢任何帮助
答案 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);
在设置新的滚动位置之前,您可以禁用当前事件处理程序并为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();
}
});
答案 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);
期间)没有发生滚动事件,则不会在第一个滚动事件上调用处理程序。在这种情况下,在第一次事件中,假事件将被取消订阅,而原始事件将被重新订阅,但不会被调用。