移动端滑动穿透方案及demo

移动端滑动穿透方案及demo

移动端滑动穿透问题通常出现在弹框出现时,上下滑动屏幕,背景也跟着滑动了

解决的办法有:
1、 加overflow:hidden

html, body {
   overflow: hidden;
}

(在移动端无效)

2、 弹窗出现时将背景设置成fixed,并记录坐标,关闭时恢复位置
(背景位置会有个跳动)

3、阻止body的默认滚动?

document.ontouchmove = e => {
	e.preventDefault();
};

(该方案好像在Android中不生效?)

下面就针对第三种方法进行优化

参考文章 龙喵 张鑫旭

我们监听 touchmove事件时,在之前是有一个小延迟触发的,因为浏览器不知道我们是否要 preventDefault,所以等到大概200ms左右才能真正收到监听回调。

chrome在56版本将 addEventListner默认的 passive置为true,具体请参见这里,这样浏览器就能知道这个 addEventListner是不用 preventDefault的,立即可触发滚动事件。

在Android的手q和微信中使用的是X5内核,它是基于blink内核的,因此同样有关于 passiveevent的优化。所以我们需要加入 addEventListner的第三个参数:

document.addEventListener(
	'touchmove',
	e => {
		e.preventDefault();
	},
	{ passive: false },
);

这样就解决了android不生效的问题,不过此时所有滑动都被禁止了,即使弹框中有超出内容,我们需要进行滑动查看。

那么,我们需要增加一个可以滚动的元素:

document.addEventListener(
  'touchmove',
  e => {
	const excludeEl = document.querySelectorAll('.can-scroll');
	const isExclude = [].some.call(excludeEl, (el: HTMLElement) =>
	  el.contains(e.target),
	);
	if (isExclude) {
	  return true;
	}
	e.preventDefault();
},
{ passive: false },

如此就解决了内容滑动的问题,可是,当滑动超出了边界时,又会触发默认的滚动穿透,这时我们又需要添加边界条件来阻止滚动:

elScroll = e.target.offsetParent || e.target
// 当前的滚动高度
scrollTop = elScroll.scrollTop;
events = e.touches[0] || e;
distanceY = events.pageY - posY;
//上下边缘检测
distanceY > 0 && scrollTop == 0
//下边缘检测
distanceY < 0 && scrollTop + 1 >= maxscroll

后来又发现要是有多个可滑动的弹框,又出现滚动穿透的问题

so, 直接上demo:





  
  
  
  Document
  



  

background

background

background

background

background

background

background

background

background

background

background

background

background

background

background

background

background

background

background

background

background

background

background

background

background

background

background

background

content

content

content

content

content

content

content

content

content

content

上面两篇参考文章写的非常好,推荐!

你可能感兴趣的:(技术)