繁体   English   中英

iOS 通过溢出滚动禁用页面滚动:触摸

[英]iOS Disable Page Scrolling with overflow-scrolling: touch

假设我们希望通过“添加到主屏幕”使 web 应用程序感觉像是本机应用程序。 第一步是禁用默认滚动。 很简单,对吧?

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

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

显而易见的解决方案如下所示:

// 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向左或向右滚动,它会恢复为默认滚动侦听器。 显然,您应该监视事件以查看touchmove事件是向左跟踪还是向右跟踪,对吗? 不幸的是,不,因为它也将在我不完全理解的情况下在容器中垂直滚动时恢复到默认滚动侦听器。

怎么办? 更糟糕的是,我们最好能够处理单个li上的click或类似点击的事件(阅读: 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事件,但由于点击和响应之间的延迟,默认目标是使 web 应用“感觉”原生。 为了解决这个问题,我们将为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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM