在iOS中,防止页面滚动时主体元素出现反弹效果,但保留子元素的反弹效果。

48

我最近一直在开发移动Web应用程序。我正在进行面向移动优化,目前专注于iPhone的iOS系统。我不想要一个精确的本地应用程序外观,但我认为具有本地感觉是绝对重要的。我已经根据这个想法制作了标记和CSS,留下了这个(为了更好地理解我后面遇到的问题而进行了注释):

Webapp markup

这一切都没有问题,它还具有本地感觉的优点,静态头部和页脚,以及可滚动的内部视图(感谢-webkit-overflow-scrolling: touch)。正如任何使用iOS超过5分钟的人所知道的那样,当您向上或向下滚动时,会出现一些不错的动量滚动。此外,当您到达列表顶部时,会出现一个漂亮的“弹跳”效果:

List bouncing in Settings.app

我觉得这有助于定义iOS的感觉,一个小细节可以产生很大的影响。幸运的是,在Web应用程序中的可滚动元素中,当您在列表顶部以下并向上滚动时,您会获得相同的效果。这就是所期望的行为:

Scrolling down and up in a webapp produces this bouncing effect

然而,当你在列表顶部,并尝试重新创建与Setting.app(如上图所示)相同的弹跳行为时,我们会得到以下不希望的行为: 向下滚动会产生整个应用程序框架的弹跳效果

我在Stack Overflow上看到了一些类似问题,但它们都选择禁用弹跳。我想知道是否有可能保持弹跳,但始终使其发生在body section section#main上,而不是在Web应用程序的框架上。我没有使用jQuery,因此我更喜欢直接使用JavaScript的答案(如果有CSS解决方案,那就更好了,额外加分)。

这里有一个GitHub仓库,包含所有代码(Sinatra、HAML和Sass;当前分支为so),或者一个JSFiddle,其中图片和链接已经损坏,但可以在iPhone上显示问题(最好将其添加到主屏幕进行测试)。


3
CSS解决方案是最理想的。我真的希望能得到一个好的答案,所以我要在这个问题上添加赏金。 - LandonSchropp
你已经看过 jQtouch 了吗?我现在使用一个较旧版本的 Datazombies 已经将近两年了,它看起来就像你所要求的那样。如果那有点过头了,你可以看看 iScroll - bart s
@barts 我刚刚查看了jQtouch,它似乎没有解决手头的问题。也许只是我自己的问题,但我在我的iPhone上尝试了演示,它似乎有同样的问题。此外,我以前见过iScroll,它总是感觉“不对劲”。动量逻辑总是有一点点偏差。即使它与iOS的逻辑完全一致,它在其他平台上也不会感觉正确。 - Kyle Lacy
我已经在这里发布了一个CSS解决方案: https://dev59.com/zmUo5IYBdhLWcg3w1yTH#18827652 关键是将内容包装在三个 -webkit-overflow-scrolling: touch divs 中。 我已经在iOS7 GM中测试了该解决方案。 - romiem
4个回答

22

2
如果我没记错的话,你的小型库选择在超出元素“边界”时禁用滚动。如果表述不够清楚,很抱歉,我的意思是要找到一种方法来允许元素上的橡皮筋效果,但不允许在页面主体上出现。 - Kyle Lacy
@zvona 很好。不过还有一个问题:如果可滚动内容在顶部,我们再次向上滚动以使“可滚动内容”反弹(而不是主体),则什么也不会发生。但这可能是操作系统的问题。不过,我认为可以通过简单地告诉列表在向上滚动到顶部时将自身设置为1像素(而不是0像素)来启用它。那么列表仍然可以反弹,对吧?也许有更新的空间?=D - cocoa coder
1
这看起来是个好主意,但当我实现它时,它只是禁用了所有地方的滚动。我不知道我是否做错了什么。 - marcgg
这是实际js文件的链接:https://gist.github.com/justVitalius/7143040#file-nonbounce-js - whyoz
也许我做错了什么,但是这个插件强制我使用两根手指滚动并阻止单指滚动。 - Jacob Raccuia
显示剩余7条评论

5
我遇到了同样的问题,并想出了以下解决方案:

http://demo.josefkjaergaard.com/stackoverflow/element_scroll/index.html

基本上,我防止滚动内容处于其最大位置。这可以防止激活body-scroll。
它起作用,但在缓动结束时会产生一点捕捉感。通过更多的工作,可能可以通过将内容朝相反方向偏移来隐藏这种行为。

这是目前为止最接近的了。关于那个发生的1 2像素的“捕捉”,有任何更新吗? - sheriffderek
我喜欢这种逻辑。与其防止条件的结果(例如,当div滚动到顶部时页面反弹),不如预防条件本身。太棒了。我尝试过几种不同的“解决方案”。这是我找到的最好的。 - Alan M.
为什么要使用document.getElementById("content").scrollHeight - $("#content").height();而不是document.getElementById("content").scrollHeight - document.getElementById("content").height();或者使用变量var content = document.getElementById("content") -> 然后再使用它? - AGDM

1

1
请不要只是链接到一堆其他网站。解释每个网站是什么以及为什么相关会非常有帮助。否则,你只会让用户陷入无尽的链接点击中。 - Joseph Yancey

0
这个伪代码怎么样?
document.body.addEventListener("ontouchstart", function(event) {
  if(document.getElementById("main").scrollTop > 0) return;
  event.preventDefault();
  event.stopPropagation();
}, false);

1
据我所知,这段代码只是选择禁用超过顶部的滚动。如果我没有表达清楚,对不起,但这是我不想要的行为。相反,我希望在子元素(#main)上保持橡皮筋效果,但在body上禁用它。 - Kyle Lacy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接