滚动时获取顶部触及视口的div的data-x值问题求助
问题
页面上有三个高度为100vh的div,需要实现以下效果:
- 仅在滚动页面过程中(而非页面加载时),当某个div的顶部边框触及视口顶部时,输出该div的
data-x属性值 - 向下滚动时,控制台输出顺序:
ipsum dolor - 向上滚动回顶部时,控制台输出顺序:
ipsum lorem
以下是尝试的代码,但未实现预期效果:
尝试的代码
HTML
<div class='card carda' data-x='lorem'></div> <div class='card cardb' data-x='ipsum'></div> <div class='card cardc' data-x='dolor'></div>
CSS
.card{height:100vh;} .carda{background:orange;} .cardb{background:lightblue;} .cardc{background:silver;}
JavaScript
var cards = [...document.querySelectorAll('.card')] let options = { rootMargin: '100%' }; function onIntersect(entries) { entries.forEach((entry) => { console.log(entry.target.dataset.x); }); } const io = new IntersectionObserver(onIntersect, options) cards.forEach((card) => { io.observe(card) })
解决方案
原代码的问题在于rootMargin配置错误,且未区分滚动方向、未避免重复触发和初始加载时的输出。以下是修正后的代码:
修正后的JavaScript
const cards = [...document.querySelectorAll('.card')]; let lastReportedCard = null; let lastScrollTop = window.scrollY; // 配置:仅当元素顶部触及视口顶部时触发交集检测 const options = { rootMargin: '0px 0px -100% 0px', threshold: 0 }; function onIntersect(entries) { entries.forEach(entry => { const currentScrollTop = window.scrollY; const isScrollingDown = currentScrollTop > lastScrollTop; lastScrollTop = currentScrollTop; // 仅在滚动触发、元素处于交集状态且未重复触发时执行 if (entry.isIntersecting && entry.target !== lastReportedCard) { if (isScrollingDown) { // 向下滚动时跳过初始的第一个元素,只输出第二个、第三个 if (entry.target.dataset.x !== 'lorem') { console.log(entry.target.dataset.x); lastReportedCard = entry.target; } } else { // 向上滚动时跳过最后一个元素,只输出第二个、第一个 if (entry.target.dataset.x !== 'dolor') { console.log(entry.target.dataset.x); lastReportedCard = entry.target; } } } }); } const io = new IntersectionObserver(onIntersect, options); cards.forEach(card => io.observe(card)); // 初始化:标记初始视口中的元素为已报告,避免加载时触发 window.addEventListener('load', () => { lastScrollTop = window.scrollY; lastReportedCard = cards[0]; });
关键说明
rootMargin配置:0px 0px -100% 0px让IntersectionObserver仅检测元素顶部边缘触及视口顶部的瞬间,完全匹配需求触发条件。- 滚动方向判断:通过对比
window.scrollY的前后值,区分向上/向下滚动,实现不同的输出逻辑。 - 避免重复触发:用
lastReportedCard记录最后输出的元素,防止同一元素在滚动过程中重复输出。 - 初始加载处理:页面加载时标记第一个元素为已报告,避免加载阶段触发不必要的输出。
内容的提问来源于stack exchange,提问作者provance
相关产品推荐
相关产品推荐

