网络上都是一堆解决滚动穿透的,却没有一条是实现滚动穿透的方案。
小程序或者某些组件会有滚动穿透,但是如果是自己要造轮子,在某些场景下就需要去实现滚动穿透。比如我打开一个可滑动的弹框,在弹框上打开一个可滑动的组件,但是这个可滑动的组件在弹框的底部,高度不确定且又要让这个可滑动组件定位到弹框子item下面,这样子可能会导致这个可滑动组件的位置被底部遮挡或位置无法调整,无法滚动父级实现组件位置的调整,造成体验低下。
这里滚动穿透的核心就是:
1、position: fixed;保证元素覆盖父级
2、pointer-events: none;取消这个元素的事件实现事件穿透,但因为pointer-events没有单独指定某个事件,所以要js支持
3、监听鼠标滚轮事件,滚动时才添加pointer-events: none;,不滚动就取消添加。
简单代码示例:
html
<!--
* @轮子的作者: 轮子哥
* @Date: 2023-12-15 10:14:35
* @LastEditTime: 2023-12-15 14:43:16
-->
<div class="container">
<div class="item">我是父级虚拟滑动列表</div>
<div class="item">我是父级虚拟滑动列表</div>
<div class="item">
<div class="mask" onclick="writess()">
实现滚动穿透(遮罩层),尝试在此遮罩区域滚动试试。
</div>
<div class="maskOv">
<div class="maskItem">我是根据父级item定位的模拟滑动下拉框</div>
<div class="maskItem">我是根据父级item定位的模拟滑动下拉框</div>
<div class="maskItem">我是根据父级item定位的模拟滑动下拉框</div>
<div class="maskItem">我是根据父级item定位的模拟滑动下拉框</div>
<div class="maskItem">我是根据父级item定位的模拟滑动下拉框</div>
<div class="maskItem">我是根据父级item定位的模拟滑动下拉框</div>
<div class="maskItem">我是根据父级item定位的模拟滑动下拉框</div>
<div class="maskItem">我是根据父级item定位的模拟滑动下拉框</div>
<div class="maskItem">我是根据父级item定位的模拟滑动下拉框</div>
</div>
</div>
<div class="item">我是父级虚拟滑动列表</div>
<div class="item">我是父级虚拟滑动列表</div>
<div class="item">我是父级虚拟滑动列表</div>
<div class="item">我是父级虚拟滑动列表</div>
<div class="item">我是父级虚拟滑动列表</div>
<div class="item">我是父级虚拟滑动列表</div>
<div class="item">我是父级虚拟滑动列表</div>
<div class="item">我是父级虚拟滑动列表</div>
</div>
<div class="writeDom"></div>
<style>
.container {
position: relative;
overflow: scroll;
height: 500px;
background: red;
}
.mask {
position: fixed;
top: 0;
left: 0;
width: 50%;
height: 100%;
background-color: #32323229;
z-index: 1;
text-align: center;
line-height: 500px;
color: blue;
}
.scrolled {
pointer-events: none;
}
.item {
position: relative;
height: 150px;
background-color: aqua;
margin: 10px;
}
.maskOv {
overflow: auto;
height: 200px;
position: absolute;
z-index: 2;
width: 400px;
}
.maskItem {
position: relative;
height: 50px;
background-color: rgb(207, 233, 62);
margin: 10px;
}
</style>
<script>
var mask = document.querySelector(".mask");
let timer = null;
//监听滚动
mask.addEventListener("wheel", function (event) {
mask.classList.add("scrolled");
if (timer) {
clearTimeout(timer);
timer = setTimeout(() => {
timer = null;
mask.classList.remove("scrolled");
}, 300)
} else {
timer = setTimeout(() => {
timer = null;
mask.classList.remove("scrolled");
}, 300)
}
});
let writeDom = document.querySelector(".writeDom");
function writess() {
console.log("点击触发,保留其它事件,仅实现滚动穿透")
writeDom.innerHTML = "点击触发,保留其它事件,仅实现滚动穿透" + new Date()
}
</script>