Mar*_*ark 27 jquery web-applications rubber-band
这个:
$('body').on('touchmove', function(e) { e.preventDefault(); });
Run Code Online (Sandbox Code Playgroud)
可以工作,但会禁用整个页面的滚动,这远非理想.
这个:
$('*').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;
});
Run Code Online (Sandbox Code Playgroud)
适用于具有滚动区域的页面.然而,当没有任何东西要滚动时,它将再次显示橡皮筋.
所以我的问题:
如何禁用橡皮筋效果并保持-webkit-overflow-scrolling区域可滚动?
[更新]
最佳方案
禁用所有不可滚动元素(如选项卡栏或导航栏)上的滚动.
anElement.addEventListener('touchmove', function( event ){ event.preventDefault() };
Run Code Online (Sandbox Code Playgroud)
将滚动处理程序附加到可滚动元素(例如主要内容).
anElement.addEventListener('touchstart', function( event ){
if( this.scrollTop === 0 ) {
this.scrollTop += 1;
} else if( this.scrollTop + this.offsetHeight >= this.scrollHeight ) {
this.scrollTop -= 1;
}
}
Run Code Online (Sandbox Code Playgroud)
Tim*_*all 30
最近在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();
}
});
Run Code Online (Sandbox Code Playgroud)
以下是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; }
Run Code Online (Sandbox Code Playgroud)
你只需要一个库(jQuery或Zepto),你就可以获得动态的原生滚动,并且身体上没有橡皮筋.另外,我添加了translateZ来修复我在滚动过程中消失的元素时遇到的一些问题,它可以用于GPU加速元素.
但是,这是一个很大但是,正如dSquared所指出的那样,当滚动元素达到极限并试图进一步滚动时整个页面橡皮筋.就个人而言,我认为这是一个失败,所以我继续努力,只是想插手试图解决这个问题.沿OP的代码添加一个检查可能是答案,但我还没有尝试过.
更新(10/7/12):
经过大量的工作,我已经得到以下代码在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);
Run Code Online (Sandbox Code Playgroud)
不幸的是,由于Mobile Safari上的橡皮筋滚动是浏览器本身的内置"功能",因此没有"神奇的子弹"修复.通过使用浏览器提供的任何默认滚动机制,您将最终在某种程度上进行橡皮筋滚动.
我建议有两种解决方法:
方法1
绑定到元素touchmove上的事件</body>并检查touchmove事件的目标,以查看是否要触发该事件:
HTML
<div class="scroll">
<p>...</p>
<p>...</p>
</div>
Run Code Online (Sandbox Code Playgroud)
JS
$('body').on('touchmove', function(e) {
// this is the node the touchmove event fired on
// in this example it would be the </p> element
target = e.target;
// we need to find the parent container
// we get it like so; assumes div as parent
parent = $(e.target).closest('div');
// check if the parent is a scroll window by class //
if ($(parent).hasClass('scroll')){
// ignore as we want the scroll to happen
} else {
e.preventDefault();
}
});
Run Code Online (Sandbox Code Playgroud)
此方法使用浏览器的默认滚动,但它的缺点是在滚动的顶部或底部仍然会有橡皮筋滚动</div>.
方法2
像以前一样绑定到元素的touchmove事件</body>,但在这种情况下,我们阻止所有 touchmove事件并依赖优秀的iScroll 4插件来处理滚动,如下所示:
HTML
<div id="wrapper">
<div id="scroller">
<p>...</p>
<p>...</p>
</div>
</div>
Run Code Online (Sandbox Code Playgroud)
JS
$(document).ready(function(){
// prevent all scroll //
$('body').on('touchmove', function(e) {
e.preventDefault();
});
// apply iscroll to scrolling element
// requires use of id
var newscroll = new iScroll('wrapper');
});??
Run Code Online (Sandbox Code Playgroud)
这是我首选的方法,因为它阻止所有橡皮筋滚动并提供一个很好的滚动区域,但它依赖于插件的使用.
我希望这有帮助
| 归档时间: |
|
| 查看次数: |
28389 次 |
| 最近记录: |