阻止整页滚动iOS

Aar*_*ken 12 html javascript css mobile-safari ios

在Mobile Safari下,是否可以允许一个绝对定位div的滚动而不允许整个页面在滚动到达边缘时上下跳动(弹性滚动)?

这是我面临的问题的最小工作示例:

<!doctype html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        #a, #b {
            position: absolute;
            top: 0;
            left: 0;
            height: 100%;
            padding: 10px;
            overflow: auto;
        }
        #a {
            width: 80px;
            background: #f00;
        }
        #b {
            background: #00f;
            left: 80px;
            width: 100%;
        }
    </style>
    <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
    <script>
        function pdcb(e) {
            e.preventDefault();
        }
        function npcb(e) {
            e.stopPropagation();
        }
        $(document).on('touchstart touchmove', pdcb).
                    on('touchstart touchmove', '.scrollable', npcb);
    </script>
</head>
<body>
    <div id="a" class="scrollable">
        This<br>
        should<br>
        be<br>
        scrollable<br>
        but<br>
        not<br>
        scroll<br>
        the<br>
        whole<br>
        page<br>
        This<br>
        should<br>
        be<br>
        scrollable<br>
        but<br>
        not<br>
        scroll<br>
        the<br>
        whole<br>
        page<br>
        This<br>
        should<br>
        be<br>
        scrollable<br>
        but<br>
        not<br>
        scroll<br>
        the<br>
        whole<br>
        page<br>
        This<br>
        should<br>
        be<br>
        scrollable<br>
        but<br>
        not<br>
        scroll<br>
        the<br>
        whole<br>
        page<br>
        This<br>
        should<br>
        be<br>
        scrollable<br>
        but<br>
        not<br>
        scroll<br>
        the<br>
        whole<br>
        page<br>
    </div>
    <div id="b">
        this should never scroll
    </div>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

解:

$(document).on('touchmove', function(e) {
    e.preventDefault();
}).ready(function() {
    $(".scrollable").on('touchstart', function(e) {
        this.allowUp = (this.scrollTop > 0);
        this.allowDown = (this.scrollTop < this.scrollHeight - this.clientHeight);
        this.prevTop = null;
        this.prevBot = null;
        this.lastY = e.originalEvent.pageY;
    }).on('touchmove', function(e) {
        var event = e.originalEvent;
        var up = (event.pageY > this.lastY), down = !up;
        this.lastY = event.pageY;

        if ((up && this.allowUp) || (down && this.allowDown))
            event.stopPropagation();
        else
            event.preventDefault();
    });
});
Run Code Online (Sandbox Code Playgroud)

mic*_*cho 18

最初的答案太棒了,但我解决了一些缺陷:

  • 如果元素位于顶部或底部,则不会分别向上和向下滚动.
  • 如果动态添加元素,则不会有滚动处理程序.
  • 有未使用的变量(prevTop,prevBot)

我的回答是针对那些.(注意我使用的.scroll-y,而不是.scrollable)

首先,添加以下CSS规则:

.scroll-y {
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch; /* nice webkit native scroll */
}
Run Code Online (Sandbox Code Playgroud)

.scroll-y类添加到要进行滚动的任何元素.

然后,在某处添加这个JS:

// Disable scroll for the document, we'll handle it ourselves
$(document).on('touchmove', function(e) {
  e.preventDefault();
});

// Check if we should allow scrolling up or down
$(document.body).on("touchstart", ".scroll-y", function (e) {
  // If the element is scrollable (content overflows), then...
  if (this.scrollHeight !== this.clientHeight) {
    // If we're at the top, scroll down one pixel to allow scrolling up
    if (this.scrollTop === 0) {
      this.scrollTop = 1;
    }
    // If we're at the bottom, scroll up one pixel to allow scrolling down
    if (this.scrollTop === this.scrollHeight - this.clientHeight) {
      this.scrollTop = this.scrollHeight - this.clientHeight - 1;
    }
  }
  // Check if we can scroll
  this.allowUp = this.scrollTop > 0;
  this.allowDown = this.scrollTop < (this.scrollHeight - this.clientHeight);
  this.lastY = e.originalEvent.pageY;
});

$(document.body).on('touchmove', ".scroll-y", function(e) {
  var event = e.originalEvent;
  var up = event.pageY > this.lastY;
  var down = !up;
  this.lastY = event.pageY;

  if ((up && this.allowUp) || (down && this.allowDown)) {
    event.stopPropagation();
  } else {
    event.preventDefault();
  }
});
Run Code Online (Sandbox Code Playgroud)


1nf*_*iti 11

虽然你没有触及div内容的边缘,但是你需要允许原生touchmove事件在该元素上运行(因此它可以滚动),但是你想要阻止事件冒泡DOM所以它不会触发页面主体上的滚动.

当您点击元素的边界时,您需要完全阻止原生动量滚动.

我使用的代码如下(对原作者道歉,这是根据我在互联网上找到的这个主题的教程改编的......现在似乎无法找到URL):

其中elem是您的DOM节点

elem.addEventListener('touchstart', function(event){
    this.allowUp = (this.scrollTop > 0);
    this.allowDown = (this.scrollTop < this.scrollHeight - this.clientHeight);
    this.prevTop = null; this.prevBot = null;
    this.lastY = event.pageY;
});

elem.addEventListener('touchmove', function(event){
    var up = (event.pageY > this.lastY), down = !up;
    this.lastY = event.pageY;

    if ((up && this.allowUp) || (down && this.allowDown)) event.stopPropagation();
    else event.preventDefault();
});
Run Code Online (Sandbox Code Playgroud)

我通常定义一个元素数组并循环遍历它们 - 迭代地将这些代码应用于每个元素.

祝你好运,希望这会有所帮助.