首页 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/)中�...

console.log输出结果差异:两次调用为何不同? console.log输出结果差异:两次调用为何不同? Apr 04, 2025 pm 05:12 PM

深入探讨console.log输出差异的根源本文将分析一段代码中console.log函数输出结果的差异,并解释其背后的原因。�...

前端开发中如何实现类似 VSCode 的面板拖拽调整功能? 前端开发中如何实现类似 VSCode 的面板拖拽调整功能? Apr 04, 2025 pm 02:06 PM

探索前端中类似VSCode的面板拖拽调整功能的实现在前端开发中,如何实现类似于VSCode...

See all articles