滑动穿透(锁body)最终探究

场景

当页面涌现浮层的时刻,滑动浮层的内容,一般状况下预期应该是浮层下边的内容不会转动;然则现实并非如此。
《滑动穿透(锁body)最终探究》
如图所示,浮层下边的内容并没有如设想中不受影响。

处置惩罚

先去github上搜刮一番,发明有处置惩罚此题目的开源包,简朴粗犷直接遴选了个中star的最高的(body-scroll-lock)操纵一番!
运用后发明有一些题目:

  • 安卓端全挂
  • ios端偶然会有锁不住的状况

查源码发明该包在iOS端运用制止touchmove的体式格局零丁处置惩罚,然则在其他端只是给bodyoverflow: hidden简朴处置惩罚。
因而决议写一个针对多端通用的包来处置惩罚相似的题目。

探究一:overflow: hidden

看到下边的转动肯定马上就想到了是全部viewport的转动,那末假如给body设置overflow: hidden,此时body的内容就只有一屏了,肯定不会转动了;

body { overflow: hidden; }

此计划在pc端圆满处置惩罚了我们的题目,然则事变并没有那末简朴;

再尝尝挪动端:
《滑动穿透(锁body)最终探究》
挪动端中并没有涌现期待的效果。。。
既然pc端已经有了圆满的计划,下边我们继承探究挪动端的处置惩罚计划。

探究二:body定位

上边想到给body设置overflow: hidden在挪动端并不能处置惩罚我们的题目,是不是在于body的height没有设置

  • 将html、body的高度都设置为100%
  • 给body设置相对定位(fixed);

同时运用这两个操纵好像圆满满足了我们的需求;
《滑动穿透(锁body)最终探究》
然则如图所示,每次都会将页面拉到最顶上的位置,如许看起来又不圆满了;
既然运用了定位,那末给一个top值不就定位到我们想要的位置了(智慧如我)。

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

屡次试验发明这个计划在android端中圆满到达了我们想要的效果,然则在ios端并不抱负;每次定位的时刻会有闪烁的题目;好事多磨,接着探究ios端的计划。

探究三:制止touchmove

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

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

测试发明没有到达设想中的效果,觉得这个效果并不能接收啊,制止documenttouchmove都不能制止转动的吗?

进一步的探究后发明缘由竟是这个属性

  • 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等于在iosandroidPC各个端零丁处置惩罚,保证在每一个端都能够完成圆满的效果!

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()
    原文作者:马宏建
    原文地址: https://segmentfault.com/a/1190000018945743
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞