iPhone Web App - 停止身体滚动

Posted

技术标签:

【中文标题】iPhone Web App - 停止身体滚动【英文标题】:iPhone Web App - Stop body scrolling 【发布时间】:2012-01-19 06:44:48 【问题描述】:

我正在创建一个 iPhone Web 应用程序,而您现在从 ios5 开始就可以使用 position: fixed;用于标题等。

虽然它有效,但如果您在页面顶部向上滚动,它会在您无法再滚动之前显示通常的灰色区域一段时间

有没有办法阻止这种滚动?我尝试过类似溢出:隐藏;但我似乎找不到任何东西。

附:我只想要一件事停止滚动,我有一个名为#container 的 div,我仍然希望它能够滚动。

【问题讨论】:

大概,我不知道叫什么。 我在这里发布了一个 CSS 解决方案:***.com/questions/15732466/… 关键是将内容包装在三个 -webkit-overflow-scrolling: touch div 中。我也在 iOS7 GM 中测试过这个解决方案。 【参考方案1】:

在查看了几个解决方案后,我开始创建自定义解决方案:

bouncefix.js

http://jaridmargolin.github.io/bouncefix.js/

用法:

bouncefix.add(el)

应用修复,使给定元素在滚动到极限时不再导致全身弹性反弹。

bouncefix.remove(el)

移除所有负责修复全身弹性反弹的监听器/观察器。

为什么?

Scrollfix 是一个好的开始,但是我发现了几个问题:

    只有在有可滚动内容时才有效。如果你有一个 空白页面,会出现在body上的弹跳效果。 API 未公开删除侦听器的方法。我的应用程序将 有多个页面,保留所有页面感觉不对 用户在应用中移动时附加的监听器。

如何?

它使用与滚动修复类似的方法。当您处于滚动极端之一时,就会出现问题。在 touchstart 上,我们会查看我们是在最高点还是最低点,如果我们在顶部,则添加 1px,如果我们在底部,则删除 1px。

不幸的是,这个技巧只有在我们能够设置 scrollTop 值的情况下才有效。如果内容还不能滚动,例如,您只有 1 个列表项,则整个正文将再次滚动。 Bouncefix.js 将通过使用事件委托并在触发 touchstart 时检查 scrollHeight 和 offsetHeight 来在幕后处理所有这些。在没有可滚动内容的情况下,容器上的所有滚动都被 e.preventDefault(); 阻止

【讨论】:

尽管我喜欢它停止弹跳的事实,但它完全消除了添加的类中的水平滚动。我有bouncefix.add("nobounce");在 doc.ready 中(“nobounce”在正文中)。然后紧随其后的那一行,我有bouncefix.remove("scrollable");这是我容器上的类,里面有一堆可滚动的 div。我做错了什么?【参考方案2】:

什么对我有用:

html, body, .scrollable 
    overflow: auto; 
    -webkit-overflow-scrolling: touch;

加号(使用 jQuery...)

$(function() 
  $(document).on("touchmove", function(evt)  evt.preventDefault() );
  $(document).on("touchmove", ".scrollable", function(evt)  evt.stopPropagation() );
);

evt.stopPropagation() 调用使用委托很重要,因为它也被文档捕获,但在最后一秒被取消。

实际上,这会捕获文档上的所有 touchmove 事件,但如果原始事件是从 .scrollable 冒泡出来的,我们只需 stopPropagation 而不是取消事件。

【讨论】:

overflow: auto 似乎搞乱了 iOS 上的固定位置元素。它们随着页面滚动,然后在滚动结束时卡入到位。 @stoutie 是的,我也遇到过。我通过将任何固定位置元素附加到正文(.scrollable 元素之外)来解决这个问题 我已经用这段代码在专用 div 中的对象元素上尝试了这个(和其他一些方法),但问题是当用户将网站作为应用程序保存到他们的起始页并启动时应用程序中该页面的对象。由于某种原因,反弹滚动将不会被拒绝......【参考方案3】:

试着把它放在你的 JS 文件的顶部..

document.ontouchmove = function(event)
    event.preventDefault();

这将完全阻止您滚动页面,因此您将无法看到顶部的“灰色区域”。

来源:Stop UIWebView from "bouncing" vertically?

【讨论】:

我只想要一件事停止滚动,我有一个名为#container 的 div,我仍然希望它能够滚动。 你可以在你不想滚动的元素上使用同样的东西。 另外,我很确定有一些类似这样的视口标签 我注意到这也会禁用文档中带有overflow:scroll 的任何其他元素的滚动。有什么办法可以避免这种情况发生? document.body.ontouchmove 如果您也需要页面上的轮播/滑动组件也可以工作。这样只会禁用正文滚动。【参考方案4】:

更新:

这个问题一直困扰着很多人,但这是bjrn创建的可靠解决方案:

演示: http://rixman.net/demo/scroll/ 这里有一个讨论:https://github.com/joelambert/ScrollFix/issues/2

这最初是由 ryan 发布的,以回答我的一个问题:Prevent touchmove default on parent but not child。

我希望这对某些人有所帮助。


原答案:

我实际上正在研究完全相同的问题,我遇到了这个问题:

https://github.com/joelambert/ScrollFix

我已经尝试过了,它几乎可以完美运行。如果您将所有代码复制到演示中并在 iOS 上试一试,除非您抓住黑色条并尝试滚动它,否则您将看不到灰色背景。但是,使用 Ben 提供的代码来防止这种情况发生应该很容易( preventDefault() )。

希望有所帮助(这绝对帮助了我!) 会:)

【讨论】:

嗯...它的文档清楚地写着ScrollFix doesn't prevent the page from being scrolled when if a touch is registered whilst the scrolling section is bouncing所以ScrollFix不是这个问题的解决方案。 是的,没错,但在当时,这是最好的选择。现在有更好的解决方案。我已将其添加到原始答案中。【参考方案5】:

像其他人建议的那样,我编写了一个快速函数,每当滚动到顶部或底部时,我的滚动 div 会增加一个像素,以防止整个页面被拖动。这对我的滚动 div 来说很好,但我页面上的固定 div 仍然容易受到页面拖动的影响。我无意中注意到,当我在滚动 div 顶部分层固定 div 时(由于我的凹凸功能不再拖动页面),触摸拖动事件通过固定 div 传递到下面的滚动 div 并且固定 div 没有更长的潜在页面拖动器。基于此,我认为可以在后台使用全屏滚动 div 作为整个页面的基础,以便所有拖动都可以通过,并且我在顶部的实际元素将是安全的。基础 div 需要实际滚动,所以我在其中放置了一个填充 div,并使其稍大以保证它可以滚动。它奏效了!下面是一个使用这个想法来防止页面拖动的例子。抱歉,如果这很明显或已经发布,但我在其他任何地方都没有看到它,它确实改善了我的网络应用程序。请尝试一下,如果有帮助,请告诉我。

<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">

<style>
.myDiv 
    position:absolute;
    left:0;
    width:100%;
    color:white;


.myDiv.hidden 
    top:0;
    height:100%;
    -webkit-overflow-scrolling:touch;
    overflow-y:scroll;


.myDiv.title 
    top:0;
    height:30%;
    background-color:#6297BC;


.myDiv.scroll 
    bottom:0;
    height:70%;
    -webkit-overflow-scrolling:touch;
    overflow-y:scroll;
    background-color:#ADADAD;

</style>

<script>
function setup()   
    hiddenScrollingDiv.addEventListener("scroll", preventWindowScroll);
    visibleScrollingDiv.addEventListener("scroll", preventWindowScroll);
    hiddenScrollingDiv.style.height=window.innerHeight; 
    visibleScrollingDiv.style.height=parseInt(window.innerHeight*.7)+1; 
    fillerDiv.style.height=window.innerHeight+2;
    hiddenScrollingDiv.scrollTop=1;
    visibleScrollingDiv.scrollTop=1;


function preventWindowScroll(evt) 
    if (evt.target.scrollTop==0) evt.target.scrollTop=1;
    else if (evt.target.scrollTop==(evt.target.scrollHeight-parseInt(evt.target.style.height))) evt.target.scrollTop=evt.target.scrollHeight-parseInt(evt.target.style.height)-1;

</script>
</head>

<body onload="setup()">
<div id="hiddenScrollingDiv" class="myDiv hidden"><div id="fillerDiv"></div></div>
<div id="visibleTitleDiv" class="myDiv title"><br><center>Non-scrolling Div</center></div>

<div id="visibleScrollingDiv" class="myDiv scroll">
<ul>
    <li style="height:50%">Scrolling Div</li>
    <li style="height:50%">Scrolling Div</li>
    <li style="height:50%">Scrolling Div</li>
</ul>
</div>

</body>
</html>

【讨论】:

【参考方案6】:

以前的解决方案建议:

document.ontouchmove = function(event)
    event.preventDefault();

但是,这也会停止滚动感兴趣的元素。

为了克服这个问题,可以做以下事情:

    检测感兴趣的元素(例如模态)的顶部/底部何时滚动到。 如果底部滚动到,对 ontouchmove 事件使用上述preventDefault 技术,但仅当用户尝试进一步向下滚动时。 如果用户尝试向上滚动,请不要再preventDefault。 如果滚动到顶部,反之亦然。

这是实现上述逻辑的source code。

为方便起见,还可以下载 npm 包(在 iOS 移动/桌面 safari 以及 android/桌面 Chrome 上使用 vanilla JS/React 进行测试)。

查看https://medium.com/jsdownunder/locking-body-scroll-for-all-devices-22def9615177 了解更多不同方法的说明。

【讨论】:

以上是关于iPhone Web App - 停止身体滚动的主要内容,如果未能解决你的问题,请参考以下文章

移动野生动物园 - 防止身体滚动(不使用固定位置)

iPhone Web App 闪屏延迟

iPhone App 中的 UIAlertView 动态

Web 应用程序,Android 与 Iphone 滚动

在 iPhone Web 应用程序中禁用滚动?

UIScrollView 在键盘关闭时停止滚动