如何在 iOS 网络应用程序中禁用橡皮筋? [英] How to disable rubber band in iOS web apps?

查看:19
本文介绍了如何在 iOS 网络应用程序中禁用橡皮筋?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个:

$('body').on('touchmove', function(e) { e.preventDefault(); });

有效,但会禁用整个页面的滚动,这远非理想.

Works, but will disable scrolling throughout the whole page, which is far from ideal.

这个:

$('*').on('touchstart', function(e){
    var element = $(this).get(0);

    if ( element.scrollTop <= 0 )                                           element.scrollTop = 1;
    if ( element.scrollTop + element.offsetHeight >= element.scrollHeight ) element.scrollTop = element.scrollHeight - element.offsetHeight - 1;
});

适用于具有滚动区域的页面.但是,当没有任何内容可以滚动时,它会再次显示橡皮筋.

Works on pages that have a scrolling area. However when there is nothing to scroll it will again show the rubber-band.

所以我的问题:

如何禁用橡皮筋效果并保持 -webkit-overflow-scrolling 区域可滚动?

How can you disable the rubber band effect and still keep the -webkit-overflow-scrolling areas scrollable?

[更新]

最佳解决方案

禁用所有不可滚动元素(例如标签栏或导航栏)的滚动.

Disable scrolling on all non-scrollable elements such as a tab bar or a navigation bar.

anElement.addEventListener('touchmove', function( event ){ event.preventDefault() };

将滚动处理程序附加到可滚动元素,例如主要内容.

Attach a scroll handler to the scrollable elements such as the main content.

anElement.addEventListener('touchstart', function( event ){
        if( this.scrollTop === 0 ) {
            this.scrollTop += 1;
        } else if( this.scrollTop + this.offsetHeight >= this.scrollHeight ) {
            this.scrollTop -= 1;
        }
}

推荐答案

最近在 SPA 中遇到了同样的问题,其中 橡皮筋有损于体验,但我需要在子区域滚动.非常感谢 dSquared 的建议,因为方法 1 最适合我.这是我对他的建议的小扩展,我在一个工作项目中实施了该建议,该项目一直向上查找树以查找其上具有 .scroll 类的任何元素(不仅仅是 div):

Ran into the same issue recently with a SPA where the <body> rubber-banding was detracting from the experience, but I needed scrolling in sub-areas. Many thanks to dSquared's suggestions, as Method 1 worked best for me. Here is my small expansion of his suggestion that I implemented in a project for work that looks all the way up the tree to find any elements (not just divs) that have a .scroll class on it:

// Prevent rubber-banding of the body, but allow for scrolling elements
$('body').on('touchmove', function (e) {
    var searchTerms = '.scroll, .scroll-y, .scroll-x',
        $target = $(e.target),
        parents = $target.parents(searchTerms);

    if (parents.length || $target.hasClass(searchTerms)) {
        // ignore as we want the scroll to happen
        // (This is where we may need to check if at limit)
    } else {
        e.preventDefault();
    }
});

这里是 CSS 的样子:

And here is what the CSS looks like:

body {
    height: 100%;
    overflow: hidden;
}
.scroll, .scroll-y, .scroll-x {
    -webkit-overflow-scrolling: touch;
}
.scroll > *, .scroll-y > *, .scroll-x > * {
    -webkit-transform : translateZ(0);
}
.scroll { overflow: auto; }
.scroll-y { overflow-y: auto; }
.scroll-x { overflow-x: auto; }

您只需要一个库(jQuery 或 Zepto),并且您可以获得带有动量的原生滚动,并且没有橡皮筋身体.另外,我添加了 translateZ 来解决我在滚动过程中元素消失时遇到的一些问题,它可以用于 GPU 加速你的元素.

You only need one library (jQuery or Zepto) and you get native scrolling with momentum and no rubber-banding on the body. Also, I've added the translateZ to fix some issues I've had with elements disappearing during scrolling and it can be used to GPU accelerate your elements.

但是(这是一个很大的但是),正如 dSquared 指出的那样,当滚动元素达到其极限并试图进一步滚动时,整个页面都会被橡皮筋束缚住.就我个人而言,我认为这是一个失败,所以我继续努力,只是想尝试解决这个问题.沿着 OP 的代码行添加检查可能是答案,但我还没有尝试过.

BUT (and this is a big but), as dSquared points out, the whole page rubber-bands when the scroll element is at its limit and attempted to scroll further. Personally, I consider this a failure so I'm continuing to work on it, just wanted to pitch in on trying to figure this out. Adding a check along the lines of the OP's code might be the answer, but I haven't tried it.

更新 (10/7/12):

UPDATE (10/7/12):

经过大量工作,我得到了以下代码在 iOS6 中完美运行(尚未在其他任何地方进行测试).机身上没有橡皮筋,在滚动区域极限时不再出现问题,并且始终具有原生滚动性能.显然,最初的代码要多得多,但我认为这将使行为最接近 OP 的目标.

After lots of work, I've gotten the following code working perfectly in iOS6 (haven't tested in anything else). No rubber-banding on the body, no more issues when at the limit of the scroll area, and it has native scrolling performance throughout. It's obviously a lot more code that originally, but I think this will give the behavior closest to the OP's goals.

(function registerScrolling($) {
    var prevTouchPosition = {},
        scrollYClass = 'scroll-y',
        scrollXClass = 'scroll-x',
        searchTerms = '.' + scrollYClass + ', .' + scrollXClass;

    $('body').on('touchstart', function (e) {
        var $scroll = $(e.target).closest(searchTerms),
            targetTouch = e.originalEvent.targetTouches[0];

        // Store previous touch position if within a scroll element
        prevTouchPosition = $scroll.length ? { x: targetTouch.pageX, y: targetTouch.pageY } : {};
    });

$('body').on('touchmove', function (e) {
    var $scroll = $(e.target).closest(searchTerms),
        targetTouch = e.originalEvent.targetTouches[0];

    if (prevTouchPosition && $scroll.length) {
        // Set move helper and update previous touch position
        var move = {
            x: targetTouch.pageX - prevTouchPosition.x,
            y: targetTouch.pageY - prevTouchPosition.y
        };
        prevTouchPosition = { x: targetTouch.pageX, y: targetTouch.pageY };

        // Check for scroll-y or scroll-x classes
        if ($scroll.hasClass(scrollYClass)) {
            var scrollHeight = $scroll[0].scrollHeight,
                outerHeight = $scroll.outerHeight(),

                atUpperLimit = ($scroll.scrollTop() === 0),
                atLowerLimit = (scrollHeight - $scroll.scrollTop() === outerHeight);

            if (scrollHeight > outerHeight) {
                // If at either limit move 1px away to allow normal scroll behavior on future moves,
                // but stop propagation on this move to remove limit behavior bubbling up to body
                if (move.y > 0 && atUpperLimit) {
                    $scroll.scrollTop(1);
                    e.stopPropagation();
                } else if (move.y < 0 && atLowerLimit) {
                    $scroll.scrollTop($scroll.scrollTop() - 1);
                    e.stopPropagation();
                }

                // If only moving right or left, prevent bad scroll.
                if(Math.abs(move.x) > 0 && Math.abs(move.y) < 3){
                  e.preventDefault()
                }

                // Normal scrolling behavior passes through
            } else {
                // No scrolling / adjustment when there is nothing to scroll
                e.preventDefault();
            }
        } else if ($scroll.hasClass(scrollXClass)) {
            var scrollWidth = $scroll[0].scrollWidth,
                outerWidth = $scroll.outerWidth(),

                atLeftLimit = $scroll.scrollLeft() === 0,
                atRightLimit = scrollWidth - $scroll.scrollLeft() === outerWidth;

            if (scrollWidth > outerWidth) {
                if (move.x > 0 && atLeftLimit) {
                    $scroll.scrollLeft(1);
                    e.stopPropagation();
                } else if (move.x < 0 && atRightLimit) {
                    $scroll.scrollLeft($scroll.scrollLeft() - 1);
                    e.stopPropagation();
                }
                // If only moving up or down, prevent bad scroll.
                if(Math.abs(move.y) > 0 && Math.abs(move.x) < 3){
                  e.preventDefault();
                }

                // Normal scrolling behavior passes through
            } else {
                // No scrolling / adjustment when there is nothing to scroll
                e.preventDefault();
            }
        }
    } else {
        // Prevent scrolling on non-scrolling elements
        e.preventDefault();
    }
});
})(jQuery);

这篇关于如何在 iOS 网络应用程序中禁用橡皮筋?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆