You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

滚动时获取顶部触及视口的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];
});

关键说明

  1. rootMargin配置:0px 0px -100% 0px 让IntersectionObserver仅检测元素顶部边缘触及视口顶部的瞬间,完全匹配需求触发条件。
  2. 滚动方向判断:通过对比window.scrollY的前后值,区分向上/向下滚动,实现不同的输出逻辑。
  3. 避免重复触发:用lastReportedCard记录最后输出的元素,防止同一元素在滚动过程中重复输出。
  4. 初始加载处理:页面加载时标记第一个元素为已报告,避免加载阶段触发不必要的输出。

内容的提问来源于stack exchange,提问作者provance

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 07:24:23