我有以下功能检查用户的滚动位置,以便菜单在滚过标头后固定
function checkScrolling() {
if( $(window).scrollTop() > $('.masthead').height() ) { // we check against ACTUAL height
$('.menu').addClass('fixed');
}else {
$('.menu').removeClass('fixed');
}
}
这里是桌面和触摸屏事件监听器:
$(document).bind('touchstart touchend touchcancel touchleave touchmove', function(e){
checkScrolling();
});
$(window).scroll(function(){
checkScrolling();
});
然而,触摸事件仅在触摸时可靠地使菜单固定。如果我通过向上或向下滑动来快速滚动,则在菜单固定或不固定之前会有一段延迟。
有关如何解决此问题的任何想法? 请参阅此处的代码示例:http://dev.driz.co.uk/mobileMasthead.html(已根据以下某些答案进行了修改,但仍无法在iPad或iPhone上正常运行)
更新的 阅读主题可以看出JS在滚动过程中没有发生滚动位置...... 但是......我注意到http://www.facebook.com/home/没有这个问题在我的iPad上测试时。因此,在不使用任何自定义JavaScript滚动条(如iScroll或类似功能)的情况下实现此效果绝对是可能的。
答案 0 :(得分:7)
也许我理解这个问题是错误的,但为了确保高速滚动的功能,你为什么不用纯CSS方式解决它(又称伪造'花式'效果):
<强> HTML 强>
<div id="menu2"></div>
<div class="scroll" id="scroller">
<div id="overlay"></div>
<div id="menu"></div>
</div>
使用简单的CSS:
html, body { overflow: hidden; height: 100% }
body { margin:0; padding:0; }
.scroll {
-webkit-overflow-scrolling: touch;
height:960px;
width:640px;
}
#menu2 {
width:640px;
height:20px;
background:red;
position:absolute;
z-index:-1;
}
#menu {
width:100%;
height:20px;
background:red;
z-index:0;
}
您可以看到一个有效的例子HERE。
这可能有点原始:但是嘿!有用! :)
检查提供的所有其他答案。
但请注意,“已知'将JavaScript与移动设备上的滚动结合使用会对速度带来很多麻烦。
这就是为什么我认为简单的CSS方法可能会更好。
如果您想了解JavaScript和在移动设备上滚动(以及其他功能),那么我强烈推荐阅读两篇文章:
答案 1 :(得分:5)
Facebook不使用JavaScript而是纯css:
position: -webkit-sticky;
如果我没记错,这会使元素在滚动时粘在其父容器的顶部。
答案 2 :(得分:2)
您只需将滚动事件附加到窗口,文档或正文,而不是附加到自定义容器。
在iOS上,您无法在这些硬件加速的窗口滚动行为中以编程方式做出反应。
这是一个小提琴: 包装器:
<div id="content">
一些不那么相关的CSS:
html,body,#content {
width:100%;
height:100%;
}
#content {
background-color: lightblue;
overflow:scroll;
}
将侦听器附加到容器:
function checkScrolling() {
if ($('#content').scrollTop() > mastheadHeight) {
menu.addClass('fixed');
} else {
menu.removeClass('fixed');
}
}
$('#content').scroll(function () {
checkScrolling();
});
你可以在这里看到它只适用于JS的后备:
答案 3 :(得分:2)
我曾尝试在网站的移动版本上实现粘性标头,但遇到了一系列问题。
首先也是最重要的是scroll
事件不会像在桌面上那样经常在移动设备上触发。通常它会在页面停止时触发。我不知道确切的原因,但我可以建议它是因为移动设备上的浏览器“发送”这样的任务到GPU同时CPU无法使JS对象与画布发生的事情保持同步(但这只是我的建议)。较新版本的iOS对我们来说更好,而scroll
可能适用于iPhone。
您应该使用touch
个事件。这使您可以为支持触摸输入的设备编写单独的代码版本。因此,必须寻找可靠的平台测试方法。
但touch
事件也很棘手,特别是在Android上。我认为在touchmove
事件的回调中,我将能够找出当前的坐标,并从那一点开始。
但是在Android上有这个问题https://code.google.com/p/android/issues/detail?id=5491,总结touchmove
在触摸操作的最开始时会触发一次或两次,并且不再触发。这使得它完全没用。人们建议使用preventDefault(),但你不能再使用它进行滚动。
所以我最终想到了使用CSS转换从头开始重新实现滚动。到目前为止,这是我的结果:
在您的设备上打开该链接,在桌面上打开http://jsbin.com/elaker/23/edit:您将能够编辑代码并在您的设备上实时更新,非常方便。
注意:强> 我想警告你,这个CSS滚动的东西是原始的,并且有一些已知的问题尚未解决:就像你有时可以滚动超出顶部或底部边界,或者如果你只是触摸(不移动)它仍然会滚动。臭名昭着的URL栏也不会隐藏。所以有工作要做。
答案 4 :(得分:1)
你是否需要触摸事件才能解决这个问题?现代设备应返回$(window).scroll()
个事件和scrollTop
值。在较旧的Android和pre-ios5(我认为)上,position:fixed:
没有按预期工作,因为视口的工作方式。但它已在所有新版本中得到纠正。
为了进一步调试设备,我强烈推荐使用Adobe Edge Inspect。您可以console.log
使用scrollTop查看您关注的设备是否实际上正常工作而没有任何诡计。你将获得免费版本所需的一切。
答案 5 :(得分:1)
处理滚动事件的一个好方法是不将支票附加到滚动事件 需要大量资源,并且与旧版浏览器无法很好地协作。 幸运的是,如果你只是执行一个时间循环,你可以有更多的控制权。 代码看起来像这样: (它被推特使用)
var MyMenu = $('#menu'),
didScroll = false;
$(window).scroll(function() {
didScroll = true;
});
setInterval(function() {
if ( didScroll ) {
didScroll = false;
//Do your check here
checkScrolling();
}
}, 180);
你应该把你的$('。masthead')。height()放在你的checkScrolling函数之外(在更高的范围内),因为这种操作占用了大量的资源并且总是要求jquery“选择你的元素”并计算其大小将最终使您的应用程序滞后:
var headerHeight = $('.masthead').height()
function checkScrolling()
.....
最后,您可以更改间隔属性的值(现在它是180(稍微超过60hz - 。屏幕的刷新时间)您可以使此值更大,如果您希望您的应用程序更高性能但是不太准确)
感谢John Resig和twitter: http://ejohn.org/blog/learning-from-twitter/
希望有所帮助 Ajios!
答案 6 :(得分:1)
setScrollTop: function(inTop) {
var top = Math.max(0,inTop);
if (wm.isMobile) { // should always be true for touch events
top = Math.min(top, this.listNode.clientHeight - this.listNodeWrapper.clientHeight);
if (dojo.isWebKit) {
this.listNode.style.WebkitTransform = "translate(0,-" + top + "px)";
} else if (dojo.isMoz) {
this.listNode.style.MozTransform = "translate(0,-" + top + "px)";
} else if (dojo.isOpera) {
this.listNode.style.OTransform = "translate(0,-" + top + "px)";
} else if (dojo.isIE) {
this.listNode.style.MsTransform = "translate(0,-" + top + "px)";
}
this.listNode.style.transform = "translate(0,-" + top + "px)";
this._scrollTop = top;
this._onScroll();
} else {
this.listNode.scrollTop = top + "px";
}
},
答案 7 :(得分:1)
我刚刚测试了你的功能以提高效率。你应该试试这个
function checkScrolling() {
if( $(window).scrollTop() > mastheadHeight )menu.css('position','fixed');
else menu.css('position','');
}
这将减少addClass和RemoveClass的函数调用,您的执行时间将生效。如果您想减少更多的执行时间,那么最好使用纯JavaScript
答案 8 :(得分:1)
$(document).ready(function(){
var p = $("#stop").offset().top;
$(window).scroll(function(){
if(p<$(window).scrollTop()){
console.log("div reached");
$("#stop").css({position:"fixed",top:0});
}
else{
console.log("div out");
$("#stop").css({position:"static"});
}
})
});
我认为这会对你有帮助。
jsfiddle.net中的总代码为here。
我已经在http://alexw.me/ipad2/中使用在线ipad2模拟器的 ipad测试了它,并且已经在那里工作了。所以,我认为它也适用于真正的ipad。