在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();
});
});
答案 0 :(得分:18)
原始答案太棒了,但我解决了一些缺陷:
我的回答解决了这些问题。 (请注意,我使用的是.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();
}
});
答案 1 :(得分:11)
虽然你没有触及div内容的边缘,但你需要允许原生touchmove事件对该元素起作用(因此它可以滚动),但是你想要停止事件从冒泡DOM开始,以便它不会触发页面主体上的滚动。
当你点击元素的边界时,你需要阻止原生动量完全滚动。
我使用的代码如下(对原作者道歉,这是根据我在互联网上找到的这个主题的教程改编的...似乎无法找到现在的网址):
其中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();
});
我通常定义一个元素数组并循环遍历它们 - 迭代地将这个代码应用于每个元素。
祝你好运,希望这会有所帮助。
答案 2 :(得分:0)
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>