详解滑动穿透(锁body)终极探索


Posted in Javascript onApril 16, 2019

场景

当页面出现浮层的时候,滑动浮层的内容,正常情况下预期应该是浮层下边的内容不会滚动;然而事实并非如此。

详解滑动穿透(锁body)终极探索

如图所示,浮层下边的内容并没有如想象中不受影响。

解决

先去github上搜索一番,发现有解决此问题的开源包,简单粗暴直接挑选了其中star的最高的(body-scroll-lock)操作一番!
使用后发现有一些问题:

  1. 安卓端全挂
  2. ios端偶尔会有锁不住的情况

查源码发现该包在iOS端使用禁止touchmove的方式单独处理,但是在其他端只是给body加overflow: hidden简单处理。
于是决定写一个针对多端通用的包来处理类似的问题。

 探索一:overflow: hidden

看到下边的滚动肯定立刻就想到了是整个viewport的滚动,那么如果给body设置overflow: hidden,此时body的内容就只有一屏了,肯定不会滚动了;

body { overflow: hidden; }

此方案在pc端完美解决了我们的问题,然而事情并没有那么简单;

再试试移动端:

详解滑动穿透(锁body)终极探索

移动端中并没有出现期待的效果。。。

既然pc端已经有了完美的方案,下边我们继续探索移动端的解决方案。

探索二:body定位

上边想到给body设置overflow: hidden在移动端并不能解决我们的问题,是否在于body的height没有设置

  1. 将html、body的高度都设置为100%;
  2. 给body设置绝对定位(fixed);

同时使用这两个操作似乎完美满足了我们的需求;

详解滑动穿透(锁body)终极探索

但是如图所示,每次都会将页面拉到最顶上的位置,这样看起来又不完美了;

既然使用了定位,那么给一个top值不就定位到我们想要的位置了(聪明如我)。

tips: body 设置 relative 定位会页面自身拉上去,下边留白

多次实验发现这个方案在android端中完美达到了我们想要的结果,但是在ios端并不理想;每次定位的时候会有闪动的问题;好事多磨,接着探索ios端的方案。

探索三:禁止touchmove

如果禁止掉页面的touchmove是否可行呢?话不多说就是干!
当弹出浮层的时候禁掉页面元素的touchmove

document.addEventListener('touchmove', function (event) {
  event.preventDefault()
})

测试发现没有达到想象中的效果,感觉这个结果并不能接受啊,禁止document 的touchmove都不能禁止滚动的吗?
进一步的探索后发现原因竟是这个属性

passive addEventListener第三个参数中传入

原来是浏览器做的一些优化,chrome passive-event-listeners
Passive Event Listeners是Chrome提出的一个新的浏览器特性:Web开发者通过一个新的属性passive来告诉浏览器,当前页面内注册的事件监听器内部是否会调用preventDefault函数来阻止事件的默认行为,以便浏览器根据这个信息更好地做出决策来优化页面性能。当属性passive的值为true的时候,代表该监听器内部不会调用preventDefault函数来阻止默认滑动行为,Chrome浏览器称这类型的监听器为被动(passive)监听器。
知道问题就好说了,给addEventListener传入第三个参数

document.addEventListener('touchmove', function (event) {
  event.preventDefault()
}, { passive: false })

大功告成! 突然想到,如果浮层中还需要滚动那就不GG了! so,是不是可以有选择性的禁止滚动(在浮层中元素滚动到最顶部或者最底部之后禁止滚动)。 单独处理浮层中需要滚动的元素;

targetElement.ontouchmove = function (event) {
  const clientY = event.targetTouches[0].clientY - initialClientY

  if (targetElement && targetElement.scrollTop === 0 && clientY > 0) {
    return preventDefault(event)
  }

  if (targetElement && (targetElement.scrollHeight - 1 - targetElement.scrollTop <= targetElement.clientHeight) && clientY < 0) {
    return preventDefault(event)
  }

  event.stopPropagation()
  return true
}

这个方案在ios中完美实现,但是在 android中还是有一点问题;浮层内容拉到最顶部或者最底部的时候依然会带动页面的内容有一定程度的移动。

详解滑动穿透(锁body)终极探索

tua-body-scroll-lock

终极方案来啦!

tua-body-scroll-lock即是在ios、android和PC各个端单独处理,保证在每个端都可以实现完美的效果!

demo

安装

$ npm i -S tua-body-scroll-lock
# OR
$ yarn add tua-body-scroll-lock

使用

移动端

import { lock, unlock } from 'tua-body-scroll-lock'

// 禁止滑动后还需要内部可以滚动的元素(针对移动端ios处理)
const targetElement = document.querySelector("#someElementId");

lock(targetElement)
unlock(targetElement)

PC端

tips: PC端不需要targetElement, 不传targetElement也不想要控制台提示可以传null

import { lock, unlock } from 'tua-body-scroll-lock'

lock()
unlock()

以上所述是小编给大家介绍的滑动穿透(锁body)详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
Javascript继承机制的设计思想分享
Aug 28 Javascript
新浪微博字数统计 textarea字数统计实现代码
Aug 28 Javascript
jQuery结合PHP+MySQL实现二级联动下拉列表[实例]
Nov 15 Javascript
js移除事件 js绑定事件实例应用
Nov 28 Javascript
怎样在JavaScript里写一个swing把数据插入数据库
Dec 10 Javascript
Javascript模块化编程(一)模块的写法最佳实践
Jan 17 Javascript
JavaScript作用域与作用域链深入解析
Dec 06 Javascript
jQuery实现模拟marquee标签效果
Jul 14 Javascript
js仿黑客帝国字母掉落效果代码分享
Nov 08 Javascript
jQuery实现获取table表格第一列值的方法
Mar 01 Javascript
详解Vue 动态添加模板的几种方法
Apr 25 Javascript
vue-cli 2.*中导入公共less文件的方法步骤
Nov 22 Javascript
一些手写JavaScript常用的函数汇总
Apr 16 #Javascript
浏览器事件循环与vue nextTicket的实现
Apr 16 #Javascript
理理Vue细节(推荐)
Apr 16 #Javascript
ES6知识点整理之Proxy的应用实例详解
Apr 16 #Javascript
js实现删除li标签一行内容
Apr 16 #Javascript
js实现弹出框的拖拽效果实例代码详解
Apr 16 #Javascript
重学 JS:为啥 await 不能用在 forEach 中详解
Apr 15 #Javascript
You might like
PHP生成验证码时“图像因其本身有错无法显示”的解决方法
2013/08/07 PHP
php获取目标函数执行时间示例
2014/03/04 PHP
PHP simplexml_load_file()函数讲解
2019/02/03 PHP
浅谈laravel5.5 belongsToMany自身的正确用法
2019/10/17 PHP
PHP 加密 Password Hashing API基础知识点
2020/03/02 PHP
Yii框架安装简明教程
2020/05/15 PHP
javascript代码运行不出来执行错误的可能情况整理
2013/10/18 Javascript
通过javascript把图片转化为字符画
2013/10/24 Javascript
基于jQuery实现点击最后一行实现行自增效果的表格
2016/01/12 Javascript
详解nodejs微信公众号开发——6.自定义菜单
2017/04/13 NodeJs
深入理解vue.js中$watch的oldvalue与newValue
2017/08/07 Javascript
JS实现table表格固定表头且表头随横向滚动而滚动
2017/10/26 Javascript
vue如何限制只能输入正负数及小数
2019/07/04 Javascript
扫微信小程序码实现网站登陆实现解析
2019/08/20 Javascript
Angular8 简单表单验证的实现示例
2020/06/03 Javascript
微信小程序 scroll-view的使用案例代码详解
2020/06/11 Javascript
[00:06]Yes,it worked!小卡尔成功穿越时空加入战场!
2019/07/20 DOTA
python实现文件路径和url相互转换的方法
2015/07/06 Python
Python3内置模块random随机方法小结
2019/07/13 Python
解决Django中修改js css文件但浏览器无法及时与之改变的问题
2019/08/31 Python
python如何将两个txt文件内容合并
2019/10/18 Python
哪种Python框架适合你?简单介绍几种主流Python框架
2020/08/04 Python
TensorFlow2.0使用keras训练模型的实现
2021/02/20 Python
美国演唱会订票网站:Ticketmaster美国
2017/10/05 全球购物
美国最大的船只买卖在线市场:Boat Trader
2018/08/04 全球购物
戴森英国官网:Dyson英国
2019/05/07 全球购物
空指针到底是什么
2012/08/07 面试题
应届大学生简历中的自我评价
2014/01/15 职场文书
地方课程教学计划
2015/01/19 职场文书
信息技术国培研修日志
2015/11/13 职场文书
祝福语集锦:给妹妹结婚的祝福语
2019/12/18 职场文书
Nginx下配置Https证书详细过程
2021/04/01 Servers
Django使用redis配置缓存的方法
2021/06/01 Redis
MySQL中utf8mb4排序规则示例
2021/08/02 MySQL
Python按顺序遍历并读取文件夹中文件
2022/04/29 Python
html5+实现plus.io进行拍照和图片等获取
2022/06/01 HTML / CSS