繁体   English   中英

检查元素在视口中是否可见

[英]Check if element is visible in viewport

我现在已经尝试了多种方法来做到这一点,我已经完成了 80%,但还没有完全完成。 我有不同大小的部分。 当我在相应的部分时,我试图添加一个活动的 class 的导航显示它是活动的。

代码有错误的倾向,在导航画廊内,我有一个砖石画廊,还有光滑的 slider 我不确定这是否会影响它。 但是活跃的 class 在导航中倾向于粘在画廊上。 每个部分的高度至少为 100vh。

根据 Cedric 的建议,我尝试使用交叉点观察器 API 但它有同样的问题,至少在我的实现中,它是错误的,并且即使不在视口中,画廊也以某种方式处于活动状态。

  let options = {
    root: null,
    rootMargin: '0px',
    threshold: 1
  }
  let callback = (entries, observer) => {
      console.log("callback called");
    entries.forEach(entry => {
        console.log("set active for " + entry.target.id);
        let sectionId = entry.target.id;
        navItems.each(function(){
            $(this).removeClass('active');
        });
        $("a[href='#" + sectionId + "']").addClass('active');
    });
  };

  let observer = new IntersectionObserver(callback, options);

  pageSections.each(function () {
    let target = document.querySelector("#" + $(this).attr('id'));
    observer.observe(target);
  });

 const navItems = $(".navigation-item"); const pageSections = $(".section-page"); const elementIsInView = el => { const scroll = window.scrollY || window.pageYOffset const boundsTop = el.getBoundingClientRect().top + scroll const viewport = { top: scroll, bottom: scroll + window.innerHeight, } const bounds = { top: boundsTop, bottom: boundsTop + el.clientHeight, } return ( bounds.bottom >= viewport.top && bounds.bottom <= viewport.bottom ) || ( bounds.top <= viewport.bottom && bounds.top >= viewport.top ); } $(function () { $(window).scroll(function () { pageSections.each(function () { console.log("elements to check " + $(this).attr('id')) if(elementIsInView($(this)[0])){ console.log("element is in viewport " + $(this).attr('id')) // this = the section that is visible let sectionId = $(this).attr('id'); navItems.each(function(){ $(this).removeClass('active'); }); $("a[href='#" + sectionId + "']").addClass('active'); } }) }) })
 .section-page{ height:100vh; }.navigation-fixed{ position:fixed; top:20px; left:20px; }.navigation-fixed ul li a.active{ color:red; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <nav class="navigation-fixed"> <ul> <li> <a href="#nav-contact" class="navigation-item">CONTACT</a> </li> <li> <a href="#nav-info" class="navigation-item">INFO</a> </li> <li> <a href="#nav-gallery" class="naviation-item">GALLERY</a> </li> <li> <a href="#nav-home" class="navigation-item active">Home</a> </li> </ul> </nav> <section class="section-page" id="nav-gallery">Content here</section> <section class="section-page" id="nav-info">Content here</section> <section class="section-page" id="nav-contact">Content here</section>

除了拼错 GALLERY 的 class 之外,您的代码看起来一切正常。 修好了就不再粘了。

一般来说,当您愿意向我们提供您所拥有的代码时(顺便说一句,这很有帮助),如果您可以制作 StackOverflows 特殊的 HTML+JS+CSS 片段之一,那就太棒了。 它以与您相同的方式显示所有代码,但还允许运行该代码并立即复制到可以对其进行编辑的答案。 我用这样一个片段来回答我的问题:

 const navItems = $(".navigation-item"); const pageSections = $(".section-page"); const elementIsInView = el => { const scroll = window.scrollY || window.pageYOffset const boundsTop = el.getBoundingClientRect().top + scroll const viewport = { top: scroll, bottom: scroll + window.innerHeight, } const bounds = { top: boundsTop, bottom: boundsTop + el.clientHeight, } return ( bounds.bottom >= viewport.top && bounds.bottom <= viewport.bottom ) || ( bounds.top <= viewport.bottom && bounds.top >= viewport.top ); } $(function () { $(window).scroll(function () { pageSections.each(function () { if(elementIsInView($(this)[0])){ // this = the section that is visible let sectionId = $(this).attr('id'); navItems.each(function(){ $(this).removeClass('active'); }); $("a[href='#" + sectionId + "']").addClass('active'); } }) }) })
 .section-page { height: 100vh; }.active { color: red; }.navigation-fixed { position: fixed; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <nav class="navigation-fixed"> <ul> <li> <a href="#nav-contact" class="navigation-item">CONTACT</a> </li> <li> <a href="#nav-info" class="navigation-item">INFO</a> </li> <li> <a href="#nav-gallery" class="navigation-item">GALLERY</a> </li> <li> <a href="#nav-home" class="navigation-item active">Home</a> </li> </ul> </nav> <section class="section-page">Spacing</section> <section class="section-page" id="nav-gallery">gallery here</section> <section class="section-page">Spacing</section> <section class="section-page" id="nav-info">info here</section> <section class="section-page">Spacing</section> <section class="section-page" id="nav-contact">contact here</section> <section class="section-page">Spacing</section>

这是一个使用Intersection Observer的小/基本示例我希望这会有所帮助

 // list of elements to be observed const targets = document.getElementsByClassName('section-page') const options = { root: null, // null means root is viewport rootMargin: '0px', threshold: 0.5 // trigger callback when 50% of the element is visible } function callback(entries, observer) { entries.forEach(entry => { if(entry.isIntersecting){ document.querySelector('.active').classList.remove('active'); const sectionId = entry.target.id; // identify which element is visible in the viewport at 50% document.querySelector(`[href="#${sectionId}"]`).classList.add('active'); } }); }; let observer = new IntersectionObserver(callback, options); [...targets].forEach(target => observer.observe(target));
 body { margin: 0; } main { margin: 0; display: grid; grid-template-columns: 150px 1fr; font-family: sans-serif; } #nav { list-style-type: none; }.navigation-item { color: inherit; text-decoration: none; display: block; margin-bottom: 12px; padding: 5px; }.navigation-item.active { background-color: grey; color: white; font-weight: bold; } #sections { height: 100vh; overflow: auto; }.section-page { margin: 20px; height: 100vh; box-sizing: border-box; padding: 0 20px 20px; }.section-page:nth-child(1) { background-color: crimson; }.section-page:nth-child(2) { background-color: darkgreen; }.section-page:nth-child(3) { background-color: darkorange; }.section-page:nth-child(4) { background-color: darkblue; }.content { padding-top: 20px; color: white; position: sticky; top: 0; }
 <main> <nav> <ul id="nav"> <li> <a href="#nav-home" class="navigation-item active">HOME</a> </li> <li> <a href="#nav-gallery" class="navigation-item">GALLERY</a> </li> <li> <a href="#nav-info" class="navigation-item">INFO</a> </li> <li> <a href="#nav-contact" class="navigation-item">CONTACT</a> </li> </ul> </nav> <div id="sections"> <section class="section-page" id="nav-home"> <div class="content">Home section</div> </section> <section class="section-page" id="nav-gallery"> <div class="content">Gallery section</div> </section> <section class="section-page" id="nav-info"> <div class="content">Info section</div> </section> <section class="section-page" id="nav-contact"> <div class="content">Contact section</div> </section> </div> </main>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM