jquery - 如何在 iOS Web 应用程序中禁用橡皮筋?

标签 jquery web-applications rubber-band

这个:

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

可以工作,但会禁用整个页面的滚动,这远非理想。

这个:

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

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

所以我的问题:

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

[更新]

最佳解决方案

禁用所有不可滚动元素(例如选项卡栏或导航栏)上的滚动。

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

将滚动处理程序附加到可滚动元素(例如主要内容)。

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

最佳答案

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

// 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 如下所示:

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 accelerate your elements

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

更新(2012 年 10 月 7 日):

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

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

关于jquery - 如何在 iOS Web 应用程序中禁用橡皮筋?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10357844/

相关文章:

javascript - 根据 jQuery 中的文本框值 onload 更改 CSS 样式?

javascript - 将类应用于 jquery ui 对话框

Java动态页面标题

java - 过滤crud list问题玩!框架

web-applications - 通过javascript/html将网络应用程序安装到主屏幕

c++ - opengl橡皮筋框不显示

c - 使用 XLIB 中的 XDrawRectangle 在屏幕上拖动鼠标时不需要的闪烁橡皮筋

javascript - 将输入限制为一组字符,同时显示这些字符

php - 基于网页域/站点的Javascript命令/变量

linux - 如何让电脑唱歌