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

zig*_*cko 5 javascript jquery

当您向下滚动页面时,我试图突出显示粘性目录中的当前部分项目。

目前的结构是这样的:

<div>
    <div>
        <div>
            <div>
                <h2 id="twitter-chats-for-ecommerce">Header</h2>
                <div>content...</div>
            </div>
        </div>
    </div>
</div>
Run Code Online (Sandbox Code Playgroud)

目录如下:

<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>
Run Code Online (Sandbox Code Playgroud)

锚点通过 WordPress 中的古腾堡块(在本例中为 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 );
Run Code Online (Sandbox Code Playgroud)

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

因此,如果页面上有多个可见标题,则目录中会突出显示多个项目。

在向下滚动页面时突出显示目录中的当前活动项目

理想情况下,我想它应该与该部分的 div 匹配,但 id 锚点被应用于标题,而我无法控制这一点。

有没有一种方法可以修改 JS 以某种方式只检测整个 div 部分而不仅仅是标题,这样它就只会在目录中突出显示一个项目 - 或者有比这更好的方法吗?

可以在此处看到我想要实现的完美运行的示例(请参阅右侧边栏中的“在此页面上”部分)。

小智 6

我修改了 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;
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

分叉的小提琴链接:http://jsfiddle.net/tz6yxfk3/


小智 6

这与上面的答案相同,但是是用纯 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;
      }
    }
  }
});
Run Code Online (Sandbox Code Playgroud)