iOS禁用页面使用溢出滚动进行滚动:触摸

所以我们假设我们想让一个web应用程序感觉像一个本地应用程序,并且具有“添加到主屏幕”的function。 其中的第一步是禁用默认的滚动。 很简单,对吧?

// window or document window.addEventListener("touchmove", function(event) { // no more scrolling event.preventDefault(); }, false); 

这一切都很好,直到你添加overflow-scrolling的混合。 确切地说,在iOS上,它将是-webkit-overflow-scrolling: touch

 /* #scrollable happens to be a ul */ #scrollable { overflow-y: auto; -webkit-overflow-scrolling: touch; } 

通过添加事件防护,硬件加速滚动容器不起作用,显然不是预期的效果。

明显的解决scheme看起来像这样:

 // 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); 

但是,如果您尝试在#scrollable向左或向右滚动,则此解决scheme会#scrollable一个问题,它将恢复为默认滚动侦听器。 那么显然,你应该监视这些事件,看看touchmove事件是左右跟踪的,对吗? 不幸的是,不,因为它也将在我不完全理解的情况下,当在容器中垂直滚动时恢复为默认滚动监听器。

怎么办? 更糟糕的是,我们理想的情况是能够处理单个点击事件或点击事件(阅读: 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); } 

为了解决这个问题,我们可以简单地使用click事件,但是默认情况下,由于点击和响应之间的延迟,使得webapp“感觉”本机的目标。 为了解决这个问题,我们将添加一个touchstarttouchend的事件监听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); } 

这一切都很好,但我们仍然没有解决与默认页面滚动控制一些touchmove事件的问题。 有任何想法吗?

尝试交换你的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 

这样,您只在尝试滚动不可滚动的元素时防止默认值。

您仍然有一个问题,在可滚动内容的顶部/底部开始拖动可能导致整个应用程序“反弹”。 要解决这个问题,请参阅Joe Lambert的ScrollFix 。