繁体   English   中英

阻止整页滚动iOS

[英]prevent full page scrolling 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>

解:

$(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();
    });
});

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

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

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

首先,添加以下CSS规则:

.scroll-y {
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch; /* nice webkit native scroll */
}

.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();
  }
});

虽然你没有触及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();
});

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

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

Aaron Gray提供的笔记帮助了!

见链接: http//blog.christoffer.me/six-things-i-learnt-about-ios-safaris-rubber-band-scrolling/

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="minimum-scale=1.0, width=device-width, maximum-scale=1.0, user-scalable=no, initial-scale=1">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <style>

        .page{
            font-size: 24px;
            overflow: scroll;
        }

        .menu{
            position: fixed;
            top: 0;
            bottom: 0;
            left: 0;
            width: 80%;
            background: gray;
            z-index: 1;
            font-size: 10px;
            overflow: scroll;
            /* uncomment to get smooth momentum scroll, but also a rubber band effect */
            /*-webkit-overflow-scrolling: touch;*/
        }

        .menu-item{
            padding: 10px;
            background: darkgray;
            font-size: 24px;
        }

    </style>
</head>

<body>

<div class="menu scrollable">
    <div class="menu-item">hello world</div>
    <div class="menu-item">hello world</div>
    <div class="menu-item">hello world</div>
    <div class="menu-item">hello world</div>
    <div class="menu-item">hello world</div>
    <div class="menu-item">hello world</div>
    <div class="menu-item">hello world</div>
    <div class="menu-item">hello world</div>
    <div class="menu-item">hello world</div>
    <div class="menu-item">hello world</div>
    <div class="menu-item">hello world</div>
    <div class="menu-item">hello world</div>
    <div class="menu-item">hello world</div>
    <div class="menu-item">hello world</div>
    <div class="menu-item">hello world</div>
    <div class="menu-item">hello world</div>
    <div class="menu-item">hello world</div>
    <div class="menu-item">hello world</div>
</div>

<div class="page disable-scrolling">
    Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's
    standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make
    a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting,
    remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing
    Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions
    of Lorem Ipsum.
</div>

<script>


    document.ontouchmove = function ( event ) {

        var isTouchMoveAllowed = true, target = event.target;

        while ( target !== null ) {
            if ( target.classList && target.classList.contains( 'disable-scrolling' ) ) {
                isTouchMoveAllowed = false;
                break;
            }
            target = target.parentNode;
        }

        if ( !isTouchMoveAllowed ) {
            event.preventDefault();
        }

    };

    function removeIOSRubberEffect( element ) {

        element.addEventListener( "touchstart", function () {

            var top = element.scrollTop, totalScroll = element.scrollHeight, currentScroll = top + element.offsetHeight;

            if ( top === 0 ) {
                element.scrollTop = 1;
            } else if ( currentScroll === totalScroll ) {
                element.scrollTop = top - 1;
            }

        } );

    }

    removeIOSRubberEffect( document.querySelector( ".scrollable" ) );


</script>

</body>
</html>

暂无
暂无

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

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