javascript 当节在页面上滚动时处于活动状态时,突出显示目录中的项目

sczxawaw  于 2023-02-07  发布在  Java
关注(0)|答案(3)|浏览(154)

当你向下滚动页面时,我试图在一个粘性目录中突出显示当前部分的项目。
当前结构如下所示:

<div>
    <div>
        <div>
            <div>
                <h2 id="twitter-chats-for-ecommerce">Header</h2>
                <div>content...</div>
            </div>
        </div>
    </div>
</div>

目录如下所示:

<ul>
    <li><a href="#">Item 1</a></li>
    <li><a href="#">Item 1</a></li>
    <li><a href="#twitter-chats-for-ecommerce">Twitter Chats for Ecommerce</a></li>
</ul>

锚通过WordPress中的 gutenberg 块自动应用于页眉(在本例中为h2)。
用于此操作的现有JavaScript如下所示:

(function($) {

    /* Table of contents - highlight active section on scroll */

    window.addEventListener('DOMContentLoaded', () => {

        const observer = new IntersectionObserver(entries => {
        entries.forEach(entry => {
            const id = entry.target.getAttribute('id');
            if (entry.intersectionRatio > 0) {
            document.querySelector(`nav li a[href="#${id}"]`).parentElement.classList.add('active');
            } else {
            document.querySelector(`nav li a[href="#${id}"]`).parentElement.classList.remove('active');
            }
        });
        });
    
        // Track all sections that have an `id` applied
        document.querySelectorAll('h2[id]').forEach((section) => {
        observer.observe(section);
        });
        
    });

})( jQuery );

但是,正如您从下面的示例屏幕截图中看到的,当匹配的标题(在本例中为h2)在页面上可见时,目录中的项将高亮显示。
因此,当页面上有多个标题时,TOC中会突出显示多个项目。

理想情况下,我猜它应该与section的div匹配,但是id锚被应用到了头部,我无法控制它。
有没有一种方法可以修改JS,以某种方式只检测整个div部分,而不仅仅是头部,以便它在TOC中只突出显示一个项目-或者有没有比这更好的方法?
一个例子,一个完美的工作,我想实现可以看到here(见'在本页'部分在右手边栏)。

woobm2wo

woobm2wo1#

我修改了randomdude的答案,突出显示滚动到的最低标题,这将持续突出显示该链接,直到用户向下滚动到另一个链接为止。

const anchors = $('body').find('h1');

$(window).scroll(function(){
    var scrollTop = $(document).scrollTop();
    
    // highlight the last scrolled-to: set everything inactive first
    for (var i = 0; i < anchors.length; i++){
        $('nav ul li a[href="#' + $(anchors[i]).attr('id') + '"]').removeClass('active');
    }
    
    // then iterate backwards, on the first match highlight it and break
    for (var i = anchors.length-1; i >= 0; i--){
        if (scrollTop > $(anchors[i]).offset().top - 75) {
            $('nav ul li a[href="#' + $(anchors[i]).attr('id') + '"]').addClass('active');
            break;
        }
    }
});

叉式提琴链节:http://jsfiddle.net/tz6yxfk3/

aelbi1ox

aelbi1ox2#

我想你在找这个:

$(window).scroll(function(){
    var scrollTop = $(document).scrollTop();
    var anchors = $('body').find('h1');
    
    for (var i = 0; i < anchors.length; i++){
        if (scrollTop > $(anchors[i]).offset().top - 50 && scrollTop < $(anchors[i]).offset().top + $(anchors[i]).height() - 50) {
            $('nav ul li a[href="#' + $(anchors[i]).attr('id') + '"]').addClass('active');
        } else {
            $('nav ul li a[href="#' + $(anchors[i]).attr('id') + '"]').removeClass('active');
        }
    }
});
nav {
    position: fixed;
    right: 20px;
    top: 20px;
}

div {
    height: 2000px;
}

div > h1 {
    height: 200px;
}

.active {
    color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav>
    <ul>
        <li id="whatbutton"><a href="#whatissm">What We Are</a></li>
        <li id="whybutton"><a href="#whyusesm">Why Us</a></li>
        <li id="offerbutton"><a href="#whatdoessmoffer">What We Offer</a></li>
        <li id="contactbutton"><a href="#contactus">Contact Us</a></li>
    </ul>
</nav>
<div>
    <h1 id="whatissm" name="whatissm"><span>sometexthere</span></h1>
    <h1 id="whyusesm" name="whyusesm"><span>somtexthere</span></h1>
    <h1 id="whatdoessmoffer" name="whatdoessmoffer"><span>sometexthere</span></h1>
    <h1 id="contactus" name="contactus"><span>Contact Us</span></h1>  
</div>

片尾:Making a menu class active when scrolled past
小提琴链环:http://jsfiddle.net/yrz54fqm/1/

arknldoa

arknldoa3#

这和上面的答案是一样的,但是是用纯JavaScript写的,不需要jQuery。干得好,起重机,像冠军一样工作。

const anchors = document.querySelectorAll('h1');
const links = document.querySelectorAll('nav > ul > li > a');

window.addEventListener('scroll', (event) => {
  if (typeof(anchors) != 'undefined' && anchors != null && typeof(links) != 'undefined' && links != null) {
    let scrollTop = window.scrollY;
    
    // highlight the last scrolled-to: set everything inactive first
    links.forEach((link, index) => {
      link.classList.remove("active");
    });
    
    // then iterate backwards, on the first match highlight it and break
    for (var i = anchors.length-1; i >= 0; i--) {
      if (scrollTop > anchors[i].offsetTop - 75) {
        links[i].classList.add('active');
        break;
      }
    }
  }
});

相关问题