自定义导航组件上没有 Bootstrap 的简单 Scrollspy

Simple Scrollspy without Bootstrap on custom Nav Component

我有一个 Table 个 ID 为 #TableOfContents 的目录,其中每个 href 指向一个 h2 或 h3。

我遇到的问题是,一旦路口观察者观察到航向、h2 或 h3,通过添加 class [=14] 来 突出显示 条目=] 对于 #TableOfContents 中的 link,但是一旦标题后的长内容(例如 p 段落)出现在视口中 突出显示 该部分已删除 因为标题不在视口中。

这是一个问题,因为我希望部分 (h2, h3) 仍然突出显示,直到下一个 h2 或 h3 不超过视口的一半。

我能做什么?

window.addEventListener('DOMContentLoaded', () => {
  const observer = new IntersectionObserver(entries => {
    entries.forEach(entry => {
    const id = entry.target.getAttribute('id');
      if (entry.intersectionRatio > 0) {
        document.querySelector(`#TableOfContents a[href="#${id}"]`).classList.add('side-active');
      } else {
        document.querySelector(`#TableOfContents a[href="#${id}"]`).classList.remove('side-active');
      }
    });
  });

  toc = document.querySelectorAll('#TableOfContents a');
    // get content so that link refer to it
  toc.forEach(function (link) {
    var id = link.getAttribute("href");
    var element = document.querySelector(id);
    observer.observe(element);
  });
});

在视口中标题时突出显示文本

标题不在视口中时文本不会突出显示

所以我们需要通过以下方式计算 containerBottom:

  1. 添加当前容器的顶部+下一个容器的顶部

  2. 或者如果是最后一个容器,

    当前容器的顶部 + outerHeight()

曾经那个;如果第 i 个容器处于滚动位置,则向其添加 class 并从第 i 个容器之前的所有容器中删除 class(第 18-21 行)(反向循环)

$(function () {
  // Table of contents (`ul`) that contains `a` tag in `li` which we want to highlight  
  var sectionIds = $('#TableOfContents a'); 

    $(document).on('scroll', function(){
        sectionIds.each(function(i, e){
            var container = $(this).attr('href');
            var containerOffset = $(container).offset().top; // container's top
            var nextContainer = $(sectionIds[i+1]).attr('href')

            if (i != sectionIds.length-1) {
             // if this container isn't last container
              var containerHeight = $(nextContainer).offset().top;
            } else {
             // last container's height will be outerHeight
              var containerHeight = $(container).outerHeight();
            }
            var containerBottom = containerOffset + containerHeight;

            var scrollPosition = $(document).scrollTop();
            if(scrollPosition < containerBottom - 20 && scrollPosition >= containerOffset - 20){
              for (var j = i; j >= 0; j--) {
                $(sectionIds[j]).removeClass('active');
              }  
              $(sectionIds[i]).addClass('active');
            } else{
                $(sectionIds[i]).removeClass('active');
            }
        });
    });
});

检查突出显示的第一个标题(“直线方程” h1)即使在下一个子标题("点到线的距离") 进入视野。