首頁 web前端 js教程 如何實現禁止彈跳窗底部頁面跟隨滾動

如何實現禁止彈跳窗底部頁面跟隨滾動

Jun 22, 2018 pm 02:04 PM

我們大家在做彈出層的時候,必不可少的一個元素就是蒙層,也就是遮罩層,當彈出層滾動的時候,蒙層底部的頁面一般是要求固定不動的,所以這篇文章就來跟大家介紹如何禁止彈跳視窗中蒙層底部頁面跟隨滾動的幾種方法,需要的朋友可以參考下。

場景概述

眾所周知,彈跳視窗是一種常見的互動方式,而蒙層是彈跳視窗必不可少的元素,用於隔間頁面與彈窗區塊,暫時阻斷頁面的互動。但是,在蒙層元素中滑動的時候,滑到內容的盡頭時,再繼續滑動,蒙層底部的頁面會開始滾動,顯然這不是我們想要的效果,因此需要阻止這種行為。

那麼,要如何阻止呢?請看以下分析:

方案分析

#方案一

開啟蒙層時,為body新增樣式:

overflow: hidden;
height: 100%;
登入後複製

在某些機型下,你可能還需要為根節點新增樣式:

overflow: hidden;
登入後複製

關閉蒙層時,移除以上樣式。

優點:

簡單方便,只要加入css樣式,沒有複雜的邏輯。

缺點:

相容性不好,適用於pc,行動端就尷尬了。

部分安卓機型以及safari中,無法無法阻止底部頁面捲動。

如果需要套用於行動端,那麼你可能需要方案二。

方案二

就是利用行動端的touch事件

Touch物件代表一個觸點,可以透過event.touches [0]獲取,每個觸點包含位置,大小,形狀,壓力大小,和目標element屬性。

{
screenX: 511, 
screenY: 400,//触点相对于屏幕左边沿的Y坐标
clientX: 244.37899780273438, 
clientY: 189.3820037841797,//相对于可视区域
pageX: 244.37, 
pageY: 189.37,//相对于HTML文档顶部,当页面有滚动的时候与clientX=Y 不等
force: 1,//压力大小,是从0.0(没有压力)到1.0(最大压力)的浮点数
identifier: 1036403715,//一次触摸动作的唯一标识符
radiusX: 37.565673828125, //能够包围用户和触摸平面的接触面的最小椭圆的水平轴(X轴)半径
radiusY: 37.565673828125,
rotationAngle: 0,//它是这样一个角度值:由radiusX 和 radiusY 描述的正方向的椭圆,需要通过顺时针旋转这个角度值,才能最精确地覆盖住用户和触摸平面的接触面
target: {} // 此次触摸事件的目标element
}
登入後複製

利用行動端的touch事件來阻止預設行為(這裡可以理解為頁面滾動就是預設行為)。

// node为蒙层容器dom节点
node.addEventListener('touchstart', e => {
 e.preventDefault()
}, false)
登入後複製

簡單粗暴,捲動時底部頁面也無法動彈了。如果你的蒙層內容不會有捲軸,那麼上述方法prefect。

但是,最怕空氣突然安靜,假如蒙層內容有滾動條的話,那麼它再也無法動彈了。因此我們需要寫一些js邏輯來判斷要不要阻止預設行為,複雜程度明顯增加。

具體思維:判定蒙層內容是否滾動到盡頭,是則阻止預設行為,反之任它橫行。

Tip:這裡我發現了一個小技巧,可以省略不少程式碼。在一次滑動中,若蒙層內容可以滾動,則蒙層內容滾動,過程中即使蒙層內容已滾至盡頭,只要不鬆手(可以理解為touchend事件觸發前),繼續滑動時頁面內容不會滾動,此時若鬆手再繼續捲動,則頁面內容會捲動。利用這一個小技巧,我們可以精簡優化我們的程式碼邏輯。

範例程式碼如下:

<body>
 <p class="page">
 <!-- 这里多添加一些,直至出现滚动条 -->
 <p>页面</p>
 <p>页面</p>
 <button class="btn">打开蒙层</button>
 <p>页面</p>
 </p>
 <p class="container">
 <p class="layer"></p>
 <p class="content">
  <!-- 这里多添加一些,直至出现滚动条 -->
  <p>蒙层</p>
  <p>蒙层</p>
  <p>蒙层</p>
 </p>
 </p>
</body>
登入後複製
body {
 margin: 0;
 padding: 20px;
}

.btn {
 border: none;
 outline: none;
 font-size: inherit;
 border-radius: 4px;
 padding: 1em;
 width: 100%;
 margin: 1em 0;
 color: #fff;
 background-color: #ff5777;
}

.container {
 position: fixed;
 top: 0;
 left: 0;
 bottom: 0;
 right: 0;
 z-index: 1001;
 display: none;
}

.layer {
 position: absolute;
 top: 0;
 left: 0;
 bottom: 0;
 right: 0;
 z-index: 1;
 background-color: rgba(0, 0, 0, .3);
}

.content {
 position: absolute;
 bottom: 0;
 left: 0;
 right: 0;
 height: 50%;
 z-index: 2;
 background-color: #f6f6f6;
 overflow-y: auto;
}
登入後複製
const btnNode = document.querySelector(&#39;.btn&#39;)
const containerNode = document.querySelector(&#39;.container&#39;)
const layerNode = document.querySelector(&#39;.layer&#39;)
const contentNode = document.querySelector(&#39;.content&#39;)
let startY = 0 // 记录开始滑动的坐标,用于判断滑动方向
let status = 0 // 0:未开始,1:已开始,2:滑动中

// 打开蒙层
btnNode.addEventListener(&#39;click&#39;, () => {
 containerNode.style.display = &#39;block&#39;
}, false)

// 蒙层部分始终阻止默认行为
layerNode.addEventListener(&#39;touchstart&#39;, e => {
 e.preventDefault()
}, false)

// 核心部分
contentNode.addEventListener(&#39;touchstart&#39;, e => {
 status = 1
 startY = e.targetTouches[0].pageY
}, false)

contentNode.addEventListener(&#39;touchmove&#39;, e => {
 // 判定一次就够了
 if (status !== 1) return

 status = 2

 let t = e.target || e.srcElement
 let py = e.targetTouches[0].pageY
 let ch = t.clientHeight // 内容可视高度
 let sh = t.scrollHeight // 内容滚动高度
 let st = t.scrollTop // 当前滚动高度

 // 已经到头部尽头了还要向上滑动,阻止它
 if (st === 0 && startY < py) {
 e.preventDefault()
 }

 // 已经到低部尽头了还要向下滑动,阻止它
 if ((st === sh - ch) && startY > py) {
 e.preventDefault()
 }
}, false)

contentNode.addEventListener(&#39;touchend&#39;, e => {
 status = 0
}, false)
登入後複製

問題雖然是解決了,但是回頭來看,複雜程度和程式碼量明顯增加了一個梯度。

本著簡單方便的原則,我們是不是還可以探索其他的方案呢?

既然touch事件判定比較複雜,何不跳出這個框框,另闢蹊徑,探索更適合的方案。

於是,便有了我們的方案三。

方案三

來講講我的思路,既然我們要阻止頁面滾動,那麼何不將其固定在視窗(即position: fixed),這樣它就無法滾動了,當蒙層關閉時再釋放。

position: fixed應該不用對大家太多介紹了吧,詳細的介紹大家可以參考這篇文章://www.jb51.net/article/83175.htm

#當然還有一些細節要考慮,將頁面固定視窗後,內容會回頭最頂端,這裡我們需要記錄一下,同步top值。

範例程式碼:

let bodyEl = document.body
let top = 0

function stopBodyScroll (isFixed) {
 if (isFixed) {
 top = window.scrollY

 bodyEl.style.position = &#39;fixed&#39;
 bodyEl.style.top = -top + &#39;px&#39;
 } else {
 bodyEl.style.position = &#39;&#39;
 bodyEl.style.top = &#39;&#39;

 window.scrollTo(0, top) // 回到原先的top
 }
}
登入後複製

思考總結

  • #若應用場景是pc,推薦方案一,真的是不要太方便

  • 若應用場景是h5,你可以採用方案二,但是我建議你採用方案三

  • 若應用場景是全平台,那麼方案三你不容錯過

本文到這裡也即將結束了,在這裡我強烈推薦一下方案三,原因在於簡單、方便、兼容性好,一次封裝,永久受用。

上面是我整理給大家的,希望今後對大家有幫助。

相關文章:

在Vue中有關響應式原理(詳細教程)

在angularjs中如何實作柱狀圖動態加載

在Angular作用域中scope的如何使用

#使用react如何實作選單權限控制

#

以上是如何實現禁止彈跳窗底部頁面跟隨滾動的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

前端熱敏紙小票打印遇到亂碼問題怎麼辦? 前端熱敏紙小票打印遇到亂碼問題怎麼辦? Apr 04, 2025 pm 02:42 PM

前端熱敏紙小票打印的常見問題與解決方案在前端開發中,小票打印是一個常見的需求。然而,很多開發者在實...

神秘的JavaScript:它的作用以及為什麼重要 神秘的JavaScript:它的作用以及為什麼重要 Apr 09, 2025 am 12:07 AM

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

誰得到更多的Python或JavaScript? 誰得到更多的Python或JavaScript? Apr 04, 2025 am 12:09 AM

Python和JavaScript開發者的薪資沒有絕對的高低,具體取決於技能和行業需求。 1.Python在數據科學和機器學習領域可能薪資更高。 2.JavaScript在前端和全棧開發中需求大,薪資也可觀。 3.影響因素包括經驗、地理位置、公司規模和特定技能。

如何使用JavaScript將具有相同ID的數組元素合併到一個對像中? 如何使用JavaScript將具有相同ID的數組元素合併到一個對像中? Apr 04, 2025 pm 05:09 PM

如何在JavaScript中將具有相同ID的數組元素合併到一個對像中?在處理數據時,我們常常會遇到需要將具有相同ID�...

JavaScript難以學習嗎? JavaScript難以學習嗎? Apr 03, 2025 am 12:20 AM

學習JavaScript不難,但有挑戰。 1)理解基礎概念如變量、數據類型、函數等。 2)掌握異步編程,通過事件循環實現。 3)使用DOM操作和Promise處理異步請求。 4)避免常見錯誤,使用調試技巧。 5)優化性能,遵循最佳實踐。

如何實現視差滾動和元素動畫效果,像資生堂官網那樣?
或者:
怎樣才能像資生堂官網一樣,實現頁面滾動伴隨的動畫效果? 如何實現視差滾動和元素動畫效果,像資生堂官網那樣? 或者: 怎樣才能像資生堂官網一樣,實現頁面滾動伴隨的動畫效果? Apr 04, 2025 pm 05:36 PM

實現視差滾動和元素動畫效果的探討本文將探討如何實現類似資生堂官網(https://www.shiseido.co.jp/sb/wonderland/)中�...

JavaScript的演變:當前的趨勢和未來前景 JavaScript的演變:當前的趨勢和未來前景 Apr 10, 2025 am 09:33 AM

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

console.log輸出結果差異:兩次調用為何不同? console.log輸出結果差異:兩次調用為何不同? Apr 04, 2025 pm 05:12 PM

深入探討console.log輸出差異的根源本文將分析一段代碼中console.log函數輸出結果的差異,並解釋其背後的原因。 �...

See all articles