我給body一個overflow:hidden和高度是沒有用的。手機網站上背景仍是能夠滑動,而後我給body一個touchmove的preventdefault()阻止事件,body滑動阻止了,PC上面是能夠了,可是手機上面滑動div仍是會致使底部body的滑動,我給div 一個阻止冒泡的事件stopPropagation(),手機網站上面仍是不能夠。html
解決方案
我通過反覆測試,發現滾動軸滾到底部的時候,會觸發body的滑動,那麼我就在事件滾到底部的時候對錶層的div作一個touchmove的阻止。到達滾動軸底部,向下滑動,阻止事件,向上滑動,開啓事件。爲此就要判斷touchmove的方向了。瀏覽器
var startX ,startY; $("body").on("touchstart", function(e) { e.preventDefault(); startX = e.originalEvent.changedTouches[0].pageX, startY = e.originalEvent.changedTouches[0].pageY; }); $("body").on("touchmove", function(e) { e.preventDefault(); var moveEndX = e.originalEvent.changedTouches[0].pageX, moveEndY = e.originalEvent.changedTouches[0].pageY, X = moveEndX - startX, Y = moveEndY - startY; if ( Math.abs(X) > Math.abs(Y) && X > 0 ) { alert("left 2 right"); } else if ( Math.abs(X) > Math.abs(Y) && X < 0 ) { alert("right 2 left"); } else if ( Math.abs(Y) > Math.abs(X) && Y > 0) { alert("top 2 bottom"); } else if ( Math.abs(Y) > Math.abs(X) && Y < 0 ) { alert("bottom 2 top"); } else{ alert("just touch"); } });
上面的方法是判斷touchmove的滑動方向。ide
除了上面方法判斷手機端手機滑動方向,我這裏再介紹一個方案,就是封裝一個角度函數,經過角度函數來判斷也還不錯!我這裏僅僅把這種方式實現上滑下滑左滑右滑列舉一下!函數
var startx, starty; //得到角度 function getAngle(angx, angy) { return Math.atan2(angy, angx) * 180 / Math.PI; }; //根據起點終點返回方向 1向上 2向下 3向左 4向右 0未滑動 function getDirection(startx, starty, endx, endy) { var angx = endx - startx; var angy = endy - starty; var result = 0; //若是滑動距離過短 if (Math.abs(angx) < 2 && Math.abs(angy) < 2) { return result; } var angle = getAngle(angx, angy); if (angle >= -135 && angle <= -45) { result = 1; } else if (angle > 45 && angle < 135) { result = 2; } else if ((angle >= 135 && angle <= 180) || (angle >= -180 && angle < -135)) { result = 3; } else if (angle >= -45 && angle <= 45) { result = 4; } return result; } //手指接觸屏幕 document.addEventListener("touchstart", function(e) { startx = e.touches[0].pageX; starty = e.touches[0].pageY; }, false); //手指離開屏幕 document.addEventListener("touchend", function(e) { var endx, endy; endx = e.changedTouches[0].pageX; endy = e.changedTouches[0].pageY; var direction = getDirection(startx, starty, endx, endy); switch (direction) { case 0: alert("未滑動!"); break; case 1: alert("向上!") break; case 2: alert("向下!") break; case 3: alert("向左!") break; case 4: alert("向右!") break; default: } }, false);
知道滑動方向如何判斷,那麼解決這個問題咱們能夠判斷是否滑動到底部或者頂部,假如滑動到底部,再往下滑動,就阻止滑動,往上滑動,就開啓滑動!滑動到頂部一個道理!總結代碼以下:測試
$('#haorooms底層背景').bind("touchmove", function (e) { e.preventDefault(); }); $(".滾動的父親").bind("touchstart", function (events) { startY = events.originalEvent.changedTouches[0].pageY; }); $(".滾動的父親 ul").bind("touchmove", function (e) { var ulheight = $(this).height(); var scrollTop = $(this).scrollTop(); var scrollheight = $(this)[0].scrollHeight; if (ulheight + scrollTop + 20 >= scrollheight) { //滾到底部20px左右 $(".滾動的父親").bind("touchmove", function (event) { moveEndY = event.originalEvent.changedTouches[0].pageY, theY = moveEndY - startY; if (Math.abs(theY) > Math.abs(theX) && theY > 0) { //用上面的abs()更加準確!這裏是判斷上滑仍是下滑!能夠用角度函數也能夠用上面絕對值方式! $(".滾動的父親").unbind("touchmove");//滑動到底部再往上滑動,解除阻止! } if (Math.abs(theY) > Math.abs(theX) && theY < 0) { event.preventDefault();//滑動到底部,再往下滑動,阻止滑動! } }) } if (scrollTop < 20) {//滾到頂部20px左右 $(".滾動的父親").bind("touchmove", function (event) { moveEndY = event.originalEvent.changedTouches[0].pageY, theY = moveEndY - startY; if (Math.abs(theY) > Math.abs(theX) && theY > 0) { event.preventDefault(); } if (Math.abs(theY) > Math.abs(theX) && theY < 0) { $(".滾動的父親").unbind("touchmove"); } }) } });
以上方法基本上可以阻止body的滾動,可是,有時候仍是會有問題,期待更好的解決方案!網站
張鑫旭的一種解決辦法
下面是張鑫旭的一個解決辦法,這裏我簡單的借用一下!this
CSS代碼:spa
.noscroll, .noscroll body { overflow: hidden; } .noscroll body { position: relative; }
js代碼:code
$.smartScroll = function(container, selectorScrollable) { // 若是沒有滾動容器選擇器,或者已經綁定了滾動時間,忽略 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; // 先求得是否是滾動元素或者滾動元素的子元素 var elTarget = $(event.target); if (!elTarget.length) { return; } var elScroll; // 獲取標記的滾動元素,自身或子元素皆可 if (elTarget.is(selectorScrollable)) { elScroll = elTarget; } else if ((elScroll = elTarget.parents(selectorScrollable)).length == 0) { elScroll = null; } if (!elScroll) { return; } // 當前滾動元素標記 data.elScroll = elScroll; // 垂直位置標記 data.posY = events.pageY; data.scrollY = elScroll.scrollTop(); // 是否能夠滾動 data.maxscroll = elScroll[0].scrollHeight - elScroll[0].clientHeight; }, touchmove: function () { // 若是不足於滾動,則禁止觸發整個窗體元素的滾動 if (data.maxscroll <= 0 || isSBBrowser) { // 禁止滾動 event.preventDefault(); } // 滾動元素 var elScroll = data.elScroll; // 當前的滾動高度 var scrollTop = elScroll.scrollTop(); // 如今移動的垂直位置,用來判斷是往上移動仍是往下 var events = event.touches[0] || event; // 移動距離 var distanceY = events.pageY - data.posY; if (isSBBrowser) { elScroll.scrollTop(data.scrollY - distanceY); elScroll.trigger('scroll'); return; } // 上下邊緣檢測 if (distanceY > 0 && scrollTop == 0) { // 往上滑,而且到頭 // 禁止滾動的默認行爲 event.preventDefault(); return; } // 下邊緣檢測 if (distanceY < 0 && (scrollTop + 1 >= data.maxscroll)) { // 往下滑,而且到頭 // 禁止滾動的默認行爲 event.preventDefault(); return; } }, touchend: function () { data.maxscroll = 0; } }); // 防止屢次重複綁定 container.data('isBindScroll', true); };
html以下:htm
<aside id="aside" class="aside"> <i class="aside-overlay hideAside"></i> <div class="aside-content"> <div class="module module-filter-list"> <div class="module-main scrollable"> <ul id="filters" class="sort-ul"> ....... </ul> </div> </div> </div> </aside>
使用:
$('#aside').addClass('active'); $.smartScroll($('#aside'), '.scrollable'); $('html').addClass('noscroll');
你們能夠測試一下!