能否使用Intersection Observer检测元素是否穿过视口中间线?
实现方案
完全可以实现,核心是通过 IntersectionObserver 的 rootMargin 参数将观测的有效区域压缩到视口中间线位置即可。
实现逻辑
- 默认情况下Intersection Observer的观测根是整个视口,我们可以通过设置负的
rootMargin,同时把上下边界向内收缩50%视口高度,最终得到的有效观测区域就是视口正中间高度为0的水平线 - 当目标元素和这条中间线产生交叉的时候就会触发回调,我们可以通过元素位置判断穿过的方向
代码示例
const targetEl = document.querySelector('#target') // 记录上一次元素相对于中间线的位置,用于判断穿过方向 let lastPositionAboveMiddle = null const observer = new IntersectionObserver(([entry]) => { // 视口中间线的y坐标 const viewportMiddleY = window.innerHeight / 2 // 元素顶部的y坐标 const elTopY = entry.boundingClientRect.top // 元素当前是否在中间线上方 const currentAbove = elTopY < viewportMiddleY // 当交叉状态变化时说明元素穿过了中间线 if (entry.isIntersecting) { if (lastPositionAboveMiddle !== null && lastPositionAboveMiddle !== currentAbove) { if (currentAbove) { console.log('元素从下往上穿过视口中间') } else { console.log('元素从上往下穿过视口中间') } } lastPositionAboveMiddle = currentAbove } }, { root: null, // 根为视口 rootMargin: '-50% 0px -50% 0px', // 上下各收缩50%视口高度,有效观测区为中间水平线 threshold: 0 // 只要元素和有效区有交叉就触发回调 }) // 开始观测目标元素 observer.observe(targetEl)
灵活调整说明
如果需要扩大触发的容错范围,比如中间线上下各10px的区域都算触发,可以调整rootMargin为"-calc(50% - 10px) 0px -calc(50% - 10px) 0px",这样有效观测区域就是上下20px的中间带,适配不同场景的精度需求。
内容的提问来源于stack exchange,提问作者Quddus George
相关产品推荐
相关产品推荐

