Javascript 移动safari上的粘性元素问题
我有一个元素,我希望在向下滚动时将其粘贴到页面顶部。从功能上讲,所有代码都可以工作,这要感谢其他用户。然而,当在手机上向下滚动时,粘性元素似乎落后了一点。我的意思是,每当父元素滚动时,代码似乎都在调用,它会对粘性元素进行成百上千的调整,从而使其稍微抖动 代码如下: HTML CSS 您需要做的是限制或消除调用以更新元素 还有,为什么要将滚动侦听器附加到包装器滚动处理程序内的窗口?这意味着每次调用滚动监听器时,它都会将另一个滚动监听器附加到窗口 您所需要的只是窗口上的单个处理程序,并允许传播来完成其余的工作Javascript 移动safari上的粘性元素问题,javascript,html,css,Javascript,Html,Css,我有一个元素,我希望在向下滚动时将其粘贴到页面顶部。从功能上讲,所有代码都可以工作,这要感谢其他用户。然而,当在手机上向下滚动时,粘性元素似乎落后了一点。我的意思是,每当父元素滚动时,代码似乎都在调用,它会对粘性元素进行成百上千的调整,从而使其稍微抖动 代码如下: HTML CSS 您需要做的是限制或消除调用以更新元素 还有,为什么要将滚动侦听器附加到包装器滚动处理程序内的窗口?这意味着每次调用滚动监听器时,它都会将另一个滚动监听器附加到窗口 您所需要的只是窗口上的单个处理程序,并允许传播来完成
// A debounce function wraps a function with a setTimeout,
// and then resets that timeout everytime it is called
function debounce(func, delay){
var timeout, that = this;
delay = delay || 300;
return function() {
if(timeout) clearTimeout(timeout)
timeout = setTimeout(function() {
return func.apply(that, arguments)
}, delay)
}
}
// a throttle function ensures that a function isn't
// called more than once every interval
function throttle(fn, interval, shouldDebounce){
var lastCall = 0, debouncedFn;
interval = interval || 300
if(shouldDebounce) debouncedFn = debounce(fn, interval);
return function(){
var now = (new Date()).getTime();
if(now - lastCall < interval)
return debouncedFn && debouncedFn.apply(this, arguments);
lastCall = now;
return fn.apply(this, arguments);
}
}
// create a function to set scroll listeners
function setScroller() {
var $anchor = $("#scroller-anchor"),
$scroller = $('#scroller'),
onMove = function onMove() {
var st = $(window).scrollTop(),
ot = $anchor.offset().top;
if(st > ot) {
$scroller.addClass('fixedElement');
} else {
$scroller.removeClass('fixedElement');
}
},
// Throttle the onMove function to make sure it isn't called too often
throttlededOnMove = throttle(onMove, 300);
$(window).scroll(throttlededOnMove);
}
// attach scroll listener on document ready
$(setScroller)
在我看来,一个可能的更有效的解决方案是使用position:CSS中的sticky而不是JS。您还需要提供top:0。IE的某些兼容性落后,但它已经是一个可行的解决方案。值得一查
如果您担心旧浏览器,您可能会在JS中添加一个回退功能,这仍然有些滞后什么是去盎司功能?我在答案中添加了一个示例函数。去抖动意味着如果在最后一次调用超时完成之前再次调用该函数,它将清除超时并等待again@chris更新了我的答案,以限制调用的数量,而不是取消调用,因为某些原因,这并没有像预期的那样应用我的css类。它确实进入了必要的if语句部分,但是css类从未被添加,也没有抛出任何奇怪的错误。请确保$scroller变量包含正确的元素。是否有其他事件正在该元素中添加和删除类?除此之外,jQuery中的一个bug超出了这个问题的范围。这就是我在我的应用程序中所做的,但是粘性支持还没有完全实现,所以适当限制JS回退仍然是一个好主意
$('#scroller-wrapper').scroll(function() {
var $anchor = $("#scroller-anchor");
var $scroller = $('#scroller');
var move = function() {
var st = $(window).scrollTop();
var ot = $anchor.offset().top;
if(st > ot) {
$scroller.addClass('fixedElement');
} else {
$scroller.removeClass('fixedElement');
}
};
$(window).scroll(move);
move();
});
.fixedElement {
position:fixed;
top:0;
right:0;
width:100%;
z-index:10000;
}
// A debounce function wraps a function with a setTimeout,
// and then resets that timeout everytime it is called
function debounce(func, delay){
var timeout, that = this;
delay = delay || 300;
return function() {
if(timeout) clearTimeout(timeout)
timeout = setTimeout(function() {
return func.apply(that, arguments)
}, delay)
}
}
// a throttle function ensures that a function isn't
// called more than once every interval
function throttle(fn, interval, shouldDebounce){
var lastCall = 0, debouncedFn;
interval = interval || 300
if(shouldDebounce) debouncedFn = debounce(fn, interval);
return function(){
var now = (new Date()).getTime();
if(now - lastCall < interval)
return debouncedFn && debouncedFn.apply(this, arguments);
lastCall = now;
return fn.apply(this, arguments);
}
}
// create a function to set scroll listeners
function setScroller() {
var $anchor = $("#scroller-anchor"),
$scroller = $('#scroller'),
onMove = function onMove() {
var st = $(window).scrollTop(),
ot = $anchor.offset().top;
if(st > ot) {
$scroller.addClass('fixedElement');
} else {
$scroller.removeClass('fixedElement');
}
},
// Throttle the onMove function to make sure it isn't called too often
throttlededOnMove = throttle(onMove, 300);
$(window).scroll(throttlededOnMove);
}
// attach scroll listener on document ready
$(setScroller)