解決移動端彈層滾動導(dǎo)致頁面滾動的問題

前幾天項目需求帖蔓,就是常見的移動端頁面矮瘟,點擊出現(xiàn)半透明遮罩,遮罩上面有新彈出的窗體塑娇,窗體內(nèi)部有滾動內(nèi)容芥永,但是會導(dǎo)致遮罩后面的主體頁面也發(fā)生滾動。參考了張鑫旭大神的方法钝吮,自己寫了個相對簡單的,今天把思路整理一下。(因為大神總是考慮的東西比較多奇瘦,而我們就把場景限定在解決這一個問題之下)棘催。


因業(yè)務(wù)代碼不能上傳,同時只要說明白問題就好耳标,頁面就不做過多雕琢啦醇坝。下面是HTML結(jié)構(gòu):

<body>
<p style="border: 1px solid #aaaa55;" id="btn">點擊顯示遮罩</p>
<p>1</p>
<p>2</p>
<p>3</p>
<p>4</p>
<p>5</p>
<p>6</p>
<p>7</p>
<p>8</p>
<p>9</p>
<i class="shadow"></i>
<div>
    <span>確認選擇</span>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
        <li>6</li>
        <li>7</li>
        <li>8</li>
        <li style="margin: 0;">9</li>
    </ul>
</div>
</body>

很簡單有木有?一堆P標簽是頁面默認顯示內(nèi)容次坡,第一個P是顯示遮罩的按鈕呼猪。i標簽是半透明遮罩,固定定位寬高100%砸琅,left和top值全為0宋距。div是顯示在遮罩上面的窗體,固定定位在頁面底部症脂,高度比較醒枋辍(小于內(nèi)部ul的高度,我這里是50%)诱篷,overflow設(shè)為auto壶唤。里面主要是ul>li結(jié)構(gòu),展示內(nèi)容棕所;“確認選擇“的span標簽是用來隱藏遮罩和窗體的(點出來咱還得讓它能回去不是闸盔?)。頁面顯示如下:


默認情況下

點擊按鈕遮罩及彈窗顯示

好琳省,頁面結(jié)構(gòu)大體如圖迎吵,主要是JS部分。我們都知道岛啸,移動端touch事件的默認行為就是頁面的滑動钓觉,所以也就造成了我們彈出的窗體滑到底以后,繼續(xù)下滑會導(dǎo)致頁面內(nèi)容下滑坚踩,滑到頂同樣如此荡灾。那么大體思路就有了(感謝張鑫旭大大):

  1. 當(dāng)手指touchstart的元素是我們不愿意發(fā)生滾動的時候,阻止默認行為瞬铸;
  2. 當(dāng)手指touchstart的元素是可滾動的時候批幌,不阻止默認行為;但到達邊緣的時候嗓节,阻止默認行為荧缘;

思路有了,接下來想想該怎么做拦宣。想象一個場景截粗,手指點在彈出層窗體上(touchstart)信姓,向下滑動(touchmove),到達底部即下邊緣(那么怎么判斷到了下邊緣绸罗?)意推,阻止默認事件!向上滑動同理珊蟀,只不過是在到達上邊緣的時候阻止默認事件即可菊值。


整理一下可以發(fā)現(xiàn),我們需要確定的幾個值:
1.邊緣值育灸。
也就是說我們怎么知道什么時候到上邊緣腻窒、什么時候到下邊緣?答案是通過scrollTop磅崭。上邊緣好說儿子,scrollTop為0就行了;那么下邊緣呢绽诚?我們都知道典徊,這個問題的場景就發(fā)生在,一個高度較低的盒子里包裹了一個高度比較高的內(nèi)容恩够。即子元素的高度大于父元素卒落。在我們這里div是那個高度較低(定高50%)的父元素,里面有一個span和一組ul>li結(jié)構(gòu)蜂桶。這里就需要用到兩個概念儡毕,一個是clientHeight,一個是scrollHeight扑媚。前者是視口大小腰湾,就是div能顯示的高度(其實就是我們這里設(shè)置的50%);而scrollHeight則是滾動大小疆股,指的是包含滾動內(nèi)容的元素大蟹逊弧(元素內(nèi)容的總高度)。仔細想想就能知道旬痹,用總的內(nèi)容高減去視口的高度附井,剩下的就是到達“內(nèi)容底部”所需要“走過“的距離,也就是說两残,當(dāng)我們滾動距離達到這個值時永毅,就“到底”了,即達到下邊緣人弓。


2.確定方向沼死。
當(dāng)觸摸到彈出窗體時(touchstart),記錄垂直位置startY崔赌;當(dāng)在彈出窗體上滑動時(touchmove)意蛀,記錄當(dāng)前垂直位置endY耸别,這兩個值的差可用來確定頁面方向。如果頁面向上滾(在這里把能到達上邊緣定義為“向上滾”)浸间,手指是向下的太雨,則endY減去startY大于0;如果頁面向下滾(即能到達下邊緣)魁蒜,手指是向上的,則endY減去startY小于0吩翻。如此兜看,方向可以確定。


說了這么多狭瞎,干貨來了细移,JS代碼如下(需要引入jQuery):

<script>
    let init = {
        data: {                    //數(shù)據(jù)初始化
            startY: 0,            //觸摸到窗體時垂直位置標記(touchstart)
            startScrollTop: 0,    //每次觸摸窗體時的滾動距離(touchstart)
            endScrollTop: 0,      //元素當(dāng)前的滾動距離(touchmove)
            maxScroll: 0          //下邊緣距離(元素滾動maxScroll就到底啦)
        },
        //touchstart發(fā)生的事件
        begin: function (event) {
            init.data.startY = event.targetTouches[0].pageY;
            init.data.startScrollTop = event.currentTarget.scrollTop;
            init.data.maxScroll = this.scrollHeight - this.clientHeight; //下邊緣距離(元素滾動maxScroll就到底啦)
            $(this).on('touchmove', init.move);
        },
        //touchmove發(fā)生的事件
        move: function (event) {
            let endScrollTop = this.scrollTop;
            let endY = event.targetTouches[0].pageY;   //元素當(dāng)前的垂直位置標記,與觸摸到窗體時垂直位置標記相差來確定向上滑還是向下滑
            let direction = endY - init.data.startY;   //如上所述熊锭,確定方向弧轧。
            if(direction > 0 && endScrollTop === 0){
                init.zuzhi(); //向上滑并且當(dāng)前的滾動距離為0,說明到達上邊緣碗殷,阻止默認事件
            }
            if(direction < 0 && endScrollTop + 1 >= init.data.maxScroll){
                init.zuzhi(); //向下滑并且當(dāng)前的滾動距離即將達到endScrollTop精绎,說明即將到達下邊緣,阻止默認事件
            }
            $(this).on('touchend', init.end);
        },
        end: function () {
            init.data.maxScroll = 0;
        },
        zuzhi: function (e) {
            event.preventDefault();
            return;
        },
        // 通過切換類名來控制遮罩及彈窗的顯示隱藏
        shadowToggle: function (ele, myclassName) {
            $(ele).hasClass(myclassName) ? $(ele).removeClass(myclassName) : $(ele).addClass(myclassName);
        },
    };
    $('div').on('touchstart', init.begin);
    $('.shadow').on('touchmove', init.zuzhi);
    $('#btn').on('click', function () {
        init.shadowToggle('.shadow', 'show');
        init.shadowToggle('html', 'noscroll');
        init.shadowToggle('div', 'show');
    });
    $('span').click(function () {
        init.shadowToggle('.shadow', 'show');
        init.shadowToggle('html', 'noscroll');
        init.shadowToggle('div', 'show');
    })
</script>

此方案在iPhone7Plus锌妻、iPhone6s及小米5代乃、魅族魅藍note5上測試通過。水平所限仿粹,有什么疏漏還請大家不吝賜教搁吓,期待共同進步!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末吭历,一起剝皮案震驚了整個濱河市堕仔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌晌区,老刑警劉巖摩骨,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異契讲,居然都是意外死亡仿吞,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門捡偏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來唤冈,“玉大人,你說我怎么就攤上這事银伟∧愫纾” “怎么了绘搞?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵番电,是天一觀的道長税迷。 經(jīng)常有香客問我,道長劝评,這世上最難降的妖魔是什么董饰? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任蒿褂,我火速辦了婚禮,結(jié)果婚禮上卒暂,老公的妹妹穿的比我還像新娘啄栓。我一直安慰自己,他們只是感情好也祠,可當(dāng)我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布昙楚。 她就那樣靜靜地躺著,像睡著了一般诈嘿。 火紅的嫁衣襯著肌膚如雪堪旧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天奖亚,我揣著相機與錄音淳梦,去河邊找鬼。 笑死遂蛀,一個胖子當(dāng)著我的面吹牛谭跨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播李滴,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼螃宙,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了所坯?” 一聲冷哼從身側(cè)響起谆扎,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎芹助,沒想到半個月后堂湖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡状土,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年无蜂,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蒙谓。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡斥季,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情酣倾,我是刑警寧澤舵揭,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站躁锡,受9級特大地震影響午绳,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜映之,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一拦焚、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧杠输,春花似錦耕漱、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽灾梦。三九已至峡钓,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間若河,已是汗流浹背能岩。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留萧福,地道東北人拉鹃。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像鲫忍,于是被迫代替她去往敵國和親膏燕。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容