阻止移動(dòng)端窗體滾動(dòng)的JS/CSS處理
首先CSS層面辽装,在<html>
標(biāo)簽上增加一個(gè)類名,例如noscroll
,然后配合如下CSS
和JS
代碼:
.noscroll,
.noscroll body {
overflow: hidden;
}
.noscroll body {
position: relative;
}
然后當(dāng)浮層出現(xiàn)的時(shí)候:
document.getElementsByTagName('html')[0].classList.add('noscroll');
當(dāng)浮層消失的時(shí)候:
document.getElementsByTagName('html')[0].classList.remove('noscroll');
可以讓一部分瀏覽器的窗體不能滾動(dòng),但不包括Safari
等瀏覽器捐韩,怎么辦呢?
我們可以在浮層touchmove
的時(shí)候鹃锈,阻止默認(rèn)事件達(dá)到避免滾動(dòng)的問(wèn)題荤胁,例如:
$('aside').on('touchmove', function(event) {
event.preventDefault();
});
這種處理兼容性強(qiáng),效果最好屎债,但是有一個(gè)問(wèn)題仅政,就是如果浮層自己也有滾動(dòng)垢油,那么這種處理會(huì)讓浮層里面自己的滾動(dòng)行為也無(wú)法觸發(fā),因此已旧,我們的處理要更進(jìn)一步,如下:
- 當(dāng)手指
touchstart
的元素不是滾動(dòng)容器同時(shí)不是容器的子元素的時(shí)候召娜,阻止默認(rèn)行為运褪,; - 如果手指
touchstart
的元素是滾動(dòng)容器或者容器子元素的時(shí)候玖瘸,不阻止默認(rèn)行為秸讹,但不包括滾動(dòng)到容器邊緣的時(shí)候。
完整代碼(依賴Jquery或者Zepto):
CSS
部分:
.noscroll,
.noscroll body {
overflow: hidden;
}
.noscroll body {
position: relative;
}
JS
部分:
$.smartScroll = function(container, containerScrollable) {
// 如果沒(méi)有滾動(dòng)容器選擇器雅倒,或者已經(jīng)綁定了滾動(dòng)時(shí)間璃诀,忽略
if (!selectorScrollable || container.data('isBindScroll')) {
return;
}
// 是否是搓瀏覽器
// 自己在這里添加判斷和篩選
var isSBBrowser;
var data = {
posY: 0,
maxscroll: 0
};
// 事件處理
container.on({
touchstart: function (event) {
var events = event.touches[0] || event;
// 先求得是不是滾動(dòng)元素或者滾動(dòng)元素的子元素
var elTarget = $(event.target);
if (!elTarget.length) {
return;
}
var elScroll;
// 獲取標(biāo)記的滾動(dòng)元素,自身或子元素皆可
if (elTarget.is(selectorScrollable)) {
elScroll = elTarget;
} else if ((elScroll = elTarget.parents(selectorScrollable)).length == 0) {
elScroll = null;
}
if (!elScroll) {
return;
}
// 當(dāng)前滾動(dòng)元素標(biāo)記
data.elScroll = elScroll;
// 垂直位置標(biāo)記
data.posY = events.pageY;
data.scrollY = elScroll.scrollTop();
// 是否可以滾動(dòng)
data.maxscroll = elScroll[0].scrollHeight - elScroll[0].clientHeight;
},
touchmove: function () {
// 如果不足于滾動(dòng)蔑匣,則禁止觸發(fā)整個(gè)窗體元素的滾動(dòng)
if (data.maxscroll <= 0 || isSBBrowser) {
// 禁止?jié)L動(dòng)
event.preventDefault();
}
// 滾動(dòng)元素
var elScroll = data.elScroll;
// 當(dāng)前的滾動(dòng)高度
var scrollTop = elScroll.scrollTop();
// 現(xiàn)在移動(dòng)的垂直位置劣欢,用來(lái)判斷是往上移動(dòng)還是往下
var events = event.touches[0] || event;
// 移動(dòng)距離
var distanceY = events.pageY - data.posY;
if (isSBBrowser) {
elScroll.scrollTop(data.scrollY - distanceY);
elScroll.trigger('scroll');
return;
}
// 上下邊緣檢測(cè)
if (distanceY > 0 && scrollTop == 0) {
// 往上滑,并且到頭
// 禁止?jié)L動(dòng)的默認(rèn)行為
event.preventDefault();
return;
}
// 下邊緣檢測(cè)
if (distanceY < 0 && (scrollTop + 1 >= data.maxscroll)) {
// 往下滑裁良,并且到頭
// 禁止?jié)L動(dòng)的默認(rèn)行為
event.preventDefault();
return;
}
},
touchend: function () {
data.maxscroll = 0;
}
});
// 防止多次重復(fù)綁定
container.data('isBindScroll', true);
}