前言
最近項目有個需求:需要移動端瀏覽器下的橡皮筋效果,但是頁面內(nèi)部的存在div
框需要存在滾動。由此,遇到的問題與解決過程,記錄如下。
聲明:此處只討論js控制部分,css的設(shè)置(例:overflow
的設(shè)置等)
第一步阻止橡皮筋效果
簡單粗暴的解決法,阻止瀏覽器滑動的默認行為
document.body.addEventListener('touchmove', (e) => {
e.preventDefault();
});
這里需要說明下,在IOS11.3下此寫法不能達到預(yù)期效果,需要如下代碼
document.body.addEventListener('touchmove', (e) => {
e.preventDefault();
}, { passive: false });
關(guān)于 passive: false
參考文章 passive 的事件監(jiān)聽器,關(guān)于IOS11.3下解釋參考文章ios11.3 橡皮筋效果
至此解決了阻止移動端瀏覽器的橡皮筋效果
保證內(nèi)部盒子的滾動效果
聲明:這里主要討論垂直滑動
討論:
- 需要某個盒子(
div
)可以滑動,那么就不能阻止該盒子以及該盒子后代元素的默認行為(touchmove
的滾動行為),所以我們需要識別盒子元素及其后代元素,不執(zhí)行阻止其默認行為的操作 - 當(dāng)滾動元素到達頂部時繼續(xù)向上滑時,同樣需要阻止其默認事件。滾動到底部時,繼續(xù)向下滾動也許阻止其默認行為。
綜上討論,首先判斷touch
事件觸發(fā)元素是否為滾動元素及其后代元素,若是則阻止默認事件,若否判斷為頂部且向上滑或者為底部且向下滑。上代碼
let startY = 0;
const scrollBox = document.querySelector('.scroll-box');
document.body.addEventListener('touchstart', (e) => {
startY = e.touches[0].pageY;
}, { passive: false });
document.body.addEventListener('touchmove', (e) => {
const moveY = e.touches[0].pageY;
const top = scrollBox.scrollTop;
const ch = scrollBox.clientHeight;
const sh = scrollBox.scrollHeight;
if (!isChildTarget(e.target, scrollBox)) {
e.preventDefault();
} else if ((top === 0 && moveY > startY) || (top + ch === sh && moveY < startY)) {
e.preventDefault();
}
}, { passive: false });
到這里就差不多結(jié)束了,對于函數(shù) isChildTarget
如下:
function isChildOf(child, parent, justChild = flase) {
// justChild為true則只判斷是否為子元素,若為false則判斷是否為本身或者子元素 默認為false
let parentNode;
if (justChild) {
parentNode = child.parentNode;
} else {
parentNode = child;
}
if (child && parent) {
while (parentNode) {
if (parent === parentNode) {
return true;
}
parentNode = parentNode.parentNode;
}
}
return false;
}
這下真的結(jié)束了。
如有問題, 歡迎交流學(xué)習(xí)。
如需轉(zhuǎn)載請注明出處 本文地址