防止在 iOS 上溢出/橡皮筋滚动 [英] Prevent overflow / rubberband scrolling on iOS

查看:24
本文介绍了防止在 iOS 上溢出/橡皮筋滚动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 SO 上已经有多个关于溢出/橡皮筋滚动的问题,但是

There are already multiple questions on the topic of overflow/rubberband scrolling on SO but

  1. 它们都没有提供适用于 iOS 9.3.2 上所有情况的解决方案
  2. 他们都没有提供关于问题本身的广泛和完整的信息

这就是我创建这篇文章作为知识体系的原因.

which is why I created this post as a body of knowledge.

在任何其他帖子中从未提到过的是,iOS 溢出滚动实际上是一个由两部分组成的行为.

The thing that was never mentioned in any other post is that iOS overflow scrolling is actually a two part behaviour.

这是具有 -webkit-overflow-scrolling: touch 元素的众所周知且最想要的行为,其中连续/动量滚动行为经过元素容器以平滑地减慢滚动内容.

This is the commonly known and mostly wanted behaviour of a element with -webkit-overflow-scrolling: touch where the continuous/momentum scrolling behaviour goes past the elements container to slow the scrolled content down smoothly.

当您以足够高的动量滚动元素的内容时,会发生这种情况,动量滚动超过滚动内容的长度.

It happens when you scroll the content of an element with a momentum high enough for the momentum scrolling to go past the length of the scrolled content.

有了这种行为,element.scrollTop 属性会随着元素滚动位置而变化,并且小于 0 或大于最大滚动(element.scrollHeight - element.offsetHeight).

With this behaviour the element.scrollTop property changing accordingly to the elements scroll position and being less than 0 or bigger than the maximum scroll (element.scrollHeight - element.offsetHeight).

如果您尝试将任何已经在其最小/最大滚动位置的元素滚动得更远(顶部的元素向上或底部的元素向下),则会发生此行为.然后滚动似乎冒泡"到 <body> 标签,并且整个视口都滚动了.

This behaviour occurs if you try to scroll any element already at its minimum/maximum scroll position even further than that (an element at top upwards or element at bottom downwards). Then the scroll seems to "bubble up" up to the <body> tag and the whole viewport is scrolled.

与上面相反,element.scrollTop 属性没有改变,而是 document.body.scrollTop 改变了.

In contrary to above here the element.scrollTop property does not change but document.body.scrollTop changes instead.

在这种情况下,最令人恼火的是,上述两种类型之间的切换不会立即切换.

The most irritating thing in this context is that the switch between the two types described above does not switch instantly.

输入两者之一后,您无法将焦点切换到任何其他元素(可滚动元素、按钮、链接等),因此滚动行为也不会改变.

After you enter one of both you cannot switch focus onto any other element (scrollable elements, buttons, links, ...) and thereby the scrolling behaviour does not change as well.

例如:如果你向上滚动一个已经在其顶部位置的元素,你输入溢出滚动类型2,用户最自然的反应是然后尝试向下滚动.因为焦点锁定在 body 滚动而不是 overflow scrolling type 1 它停留在 type 2 并且整个 body 向下滚动.典型的用户然后开始任意地开始频繁地上下滚动而不会突破type 2.

For instance: if you scroll a element already at its top position upwards you enter overflow scrolling type 2 and the most natural reaction for a user is to then try to scroll back down. Because the focus is locked to the body scroll instead of going to overflow scrolling type 1 it stays in type 2 and the whole body is scrolled downwards. The typical user then starts to arbitrarily starts to scroll up and down frequently without ever breaking out of type 2.

焦点的切换以及滚动行为的改变只能在溢出动画完成并且元素静止(甚至比这更长 [大约 0.5 秒])后发生.

The switch of focus and thus the change of scrolling behaviour can only occur after the overflow animation has finished and the element stands still (even a bit longer [around 0.5s] than that).

因此回到上一个示例,用户的正确反应是停止触摸屏幕大约 1 到 1.5 秒,然后再次尝试向下滚动.

thus going back to the previous example the correct reaction of the user would be to stop touching the screen for around 1s - 1.5s and then try to scroll downwards again.

推荐答案

解决方案:

类型 1:

防止元素本身溢出滚动的最基本解决方案是防止触摸事件的默认设置.

The solution:

Type 1:

The most basic solution to prevent overflow scrolling on the element itself is to prevent default on touch events.

document.body.addEventListener('touchmove', function(e) { 
    e.preventDefault(); 
});

然而,这种方法禁用了浏览器的原生动量滚动,因此不适用于大多数应用程序.但是,通过一些改进(仅防止顶部向上滚动或底部向下滚动,...)此方法解决了大多数问题.在这篇SO帖子中可以找到许多可能的实现.

This method however disables the browsers native momentum scroll and is thereby not suitable for most applications. With some refinement however (only prevent if at top scrolling up or at bottom scrolling down, ...) this method fixes most problems. Many possible implementations can be found in this SO post.

然而,上面描述的方法并不能阻止身体上的溢出滚动.

Overflow scrolling on the body however is not prevented by methods described above.

一种看似合理的可能解决方案是防止元素位于其顶部或底部位置,如提到的问题.

One possible solution which seems reasonable is to prevent the element from ever being at its top or bottom position as described as best solution on mentioned question.

anElement.addEventListener('touchstart', function( event ){
    if( this.scrollTop === 0 ) {
        this.scrollTop += 1;
    } else if( this.scrollTop + this.offsetHeight >= this.scrollHeight ) {
        this.scrollTop -= 1;
    }
}

然而,这在 iOS 9.3.2 上并不可靠.

This however did not reliably work on iOS 9.3.2.

什么起作用是在 元素上设置 position: fixed 以防止身体移动.但是请注意这仍然不能完全阻止type 2的发生,这就是为什么有时您无法滚动/聚焦任何元素,因为在后台type2 其焦点锁定仍在发生(同样,在您停止触摸屏幕片刻后,它再次按预期工作).

What did work however is setting position: fixed on the <body> element to prevent the body from moving. Please note however that this still does not completely stop type 2 from happening, which is why sometimes you cannot scroll/focus any element because in the background type2 with its focus lock is still happening (again, after you stop touching the screen for a moment it again works as expected).

虽然这还远不是最佳解决方案,但它似乎是我们目前所能得到的最好的解决方案.

While this is still far from being the optimal solution it seems to be the best we can get for the time speaking.

请注意,我不确定将 position: fixed 放在 元素上是否安全.为了跟踪可能的问题,我创建了遵循 SO 帖子.显然,最好创建一个包装元素作为 body 的子元素并将该元素设置为 position: fixed 以避免缩放问题.

Please note that I am not sure if it is safe to put position: fixed on a <body> element. To track possible issues I have created following SO post. Apparently it might be better to create a wrapper element as child of body and set that element to position: fixed to avoid zoom problemes.

脚本 iNoBounce 创造了奇迹.只需将其加载到页面即可体验无反弹的 Web 应用程序.到目前为止,我还没有发现这个解决方案有任何问题.

The script iNoBounce works wonders. Just load it to the page and experience a bounce-free web application. So far I have not found any problems with this solution.

这篇关于防止在 iOS 上溢出/橡皮筋滚动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆