javascript iOS 通过溢出滚动禁用页面滚动:触摸
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15313570/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
iOS Disable Page Scrolling with overflow-scrolling: touch
提问by skeggse
Let's say we want to make a webapp feel like a native app with "Add to Home Screen." One of the first steps is to disable the default scrolling. Easy, right?
假设我们想让一个 web 应用程序感觉像一个带有“添加到主屏幕”的本地应用程序。第一步是禁用默认滚动。很简单,对吧?
// window or document
window.addEventListener("touchmove", function(event) {
// no more scrolling
event.preventDefault();
}, false);
That's all fine and dandy until you add overflow-scrolling
to the mix. To be precise, on iOS it would be -webkit-overflow-scrolling: touch
.
在你加入overflow-scrolling
混合之前,这一切都很好。准确地说,在 iOS 上它将是-webkit-overflow-scrolling: touch
.
/* #scrollable happens to be a ul */
#scrollable {
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
By adding event prevention, hardware-accelerated scrolling in a container does not function, clearly not the intended effect.
通过添加事件预防,容器中的硬件加速滚动不起作用,显然不是预期的效果。
The obvious solution looks something like this:
显而易见的解决方案如下所示:
// you could do this for multiple elements, of course
var scrollable = document.querySelector("#scrollable");
scrollable.addEventListener("touchmove", function(event) {
// no more bubbling :)
event.stopPropagation();
}, false);
This solution introduces a problem, however, if you try to scroll left or right in #scrollable
, it reverts back to the default scroll listener. Clearly, then, you should monitor the events to see if the touchmove
event is tracking left or right, right? Unfortunately, no, as it will also, under circumstances I don't entirely understand, revert to the default scroll listener when scrolling vertically in the container.
此解决方案引入了一个问题,但是,如果您尝试在 中向左或向右滚动#scrollable
,它会恢复为默认滚动侦听器。显然,您应该监视事件以查看touchmove
事件是向左跟踪还是向右跟踪,对吗?不幸的是,不,因为在我不完全理解的情况下,它也会在容器中垂直滚动时恢复到默认滚动侦听器。
Now what? To make matters worse, we would ideally be able to handle click
or click-like events on the individual li
s (read: touchstart
):
怎么办?更糟糕的是,理想情况下,我们能够处理click
单个li
s上的或类似点击的事件(阅读:)touchstart
:
var items = scrollable.querySelectorAll("#scrollable li");
for (var item = 0; item < items.length; item++) {
items[item].addEventListener("touchstart", function() {
// handle the touch start
}, false);
}
To fix this problem, we could turn to simply using click
events, but that defaults the goal of making the webapp "feel" native due to the delay between tapping and response. To solve this, we'll add an event listener for touchstart
and touchend
:
为了解决这个问题,我们可以转向简单地使用click
事件,但由于点击和响应之间的延迟,默认目标是使 web 应用程序“感觉”原生。为了解决这个问题,我们将为touchstart
and添加一个事件监听器touchend
:
var items = scrollable.querySelectorAll("#scrollable li");
var activeItem = null, startTouch = null;
for (var item = 0; item < items.length; item++) {
items[item].addEventListener("touchstart", function(event) {
startTouch = event.touches[0];
activeItem = this;
}, false);
items[item].addEventListener("touchend", function(event) {
var touch = event.changedTouches[0];
var deltaX = touch.pageX - startTouch.pageX
var deltaY = touch.pageY - startTouch.pageY;
// require the touchstart to be within 10 pixels of the touchend
if (deltaX * deltaX + deltaY * deltaY <= 100)
// handle "click" event
}, false);
}
That's all fine and good, but we still haven't solved the problem with default page scrolling taking control of some touchmove
events. Any ideas?
这一切都很好,但我们仍然没有解决默认页面滚动控制某些touchmove
事件的问题。有任何想法吗?
采纳答案by rharper
Try swapping around the logic in your window
and scrollable
element listeners like so:
尝试在您的window
和scrollable
元素侦听器中交换逻辑,如下所示:
// window or document
window.addEventListener("touchmove", function(event) {
if (!event.target.classList.contains('scrollable')) {
// no more scrolling
event.preventDefault();
}
}, false);
// No special listeners needed on .scrollable elements
This way, you only prevent default when trying to scroll non-scrollable elements.
这样,您只能在尝试滚动不可滚动元素时阻止默认值。
You will still have a problem that at the top/bottom of the scrollable content starting a drag can cause the whole app to "bounce". To fix this problem, see Joe Lambert's ScrollFix.
您仍然会遇到一个问题,即在可滚动内容的顶部/底部开始拖动可能会导致整个应用程序“弹跳”。要解决此问题,请参阅Joe Lambert 的 ScrollFix。