如何在不使用 bootstrap 的情况下使用 scrollspy

how to use scrollspy without using bootstrap

有人知道如何在不使用 bootstrap 的情况下使用 scrollspy 吗? 我正在尝试使用此存储库让它在我的一个项目中工作:

https://github.com/sxalexander/jquery-scrollspy

但它与 bootstrap 不同。 li 标签未标记为活动 :( 任何帮助将不胜感激。

我试过这样做:

    $('#intel_nav').scrollspy({
        //n: $('#nav').offset().top,
        onEnter: function (element, position) {
            console.log(element);

            $("#intel_nav").addClass('moo');
        },
        onLeave: function (element, position) {
            $("#intel_nav").removeClass('out');
        }
    });

该元素似乎是实际的菜单,所以我不知道如何实际获取我当前悬停在其上的元素的 ID。

github.com/sxalexander/jquery-scrollspy 似乎没有像 Bootstrap 插件那样自动激活 <nav> 菜单。

但是它确实提供了进入视图的元素的 ID。请参阅在控制台中打印元素 ID 的 this JSFiddle

您需要决定如何突出显示与具有其 ID 的元素对应的菜单项。例如,在菜单 link 上设置 data-target="section1" 属性,然后当 ID 为 section1 的元素出现时,通过 $("#intel_nav a[data-target='" + "section1" + "']")

定位菜单

为了解决这个问题,我编写了自己的插件。 可以在这里找到:

https://github.com/r3plica/Scrollspy

您可以使用 bootstrap 的自定义页面仅下载 scrollspy JS。您还需要 "nav" css。这个 link 应该正是您所需要的:http://getbootstrap.com/customize/?id=8f4a63b0157214af61c9ce380630a64d

下载 JS 和 CSS 文件并将它们添加到您的站点。 Scrollspy 应该按照 bootstrap 的文档工作 (http://getbootstrap.com/javascript/#scrollspy)

如果有人仍然对此感兴趣,我无法使 bootstrap scrollspy 足够快地工作,所以我编写了自己的(技术上效率低下但简单)解决方案。

这是一个演示:

$(window).bind('scroll', function() {
    var currentTop = $(window).scrollTop();
    var elems = $('.scrollspy');
    elems.each(function(index){
      var elemTop  = $(this).offset().top;
      var elemBottom  = elemTop + $(this).height();
      if(currentTop >= elemTop && currentTop <= elemBottom){
        var id   = $(this).attr('id');
        var navElem = $('a[href="#' + id+ '"]');
    navElem.parent().addClass('active').siblings().removeClass( 'active' );
      }
    })
}); 
.active{
  color: red;
  background-color: red;
}

#nav{
  position:fixed;
  top:0;
  right:50%;
}

section{
  min-height: 500px;
}
<html>
 <head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
   </head>
   <body>
      <nav id="nav" class="navbar navbar-template">
        <div class="row col-xs-12 text-center">
          <ul>
            <li class="active">
              <a href="#Home">Home</a>
            </li>
            <li>
              <a href="#AboutUs">AboutUs</a>
            </li>
            <li>
              <a href="#Images">Images</a>
            </li>
            <li>
              <a href="#Contact">Contact</a>
            </li>
          </ul>
        </div>
      </nav>

      <section class="scrollspy" id="Home">
      Home
      </section>

      <section class="scrollspy" id="AboutUs">
      AboutUs
      </section>

      <section class="scrollspy" id="Images">
      Images
      </section>

      <section class="scrollspy" id="Contact">
      Contact
      </section>
</body>

在查看所有建议后,我遵循 Gyrocode.com idea, with the Mr. Sam Alexander (sxalexander) jquery-scrollspy, a nicely work based on David Walsh's MooTools scrollspy; I believe that is not to hard use this with any menu (with or without nav) or in any creative duty as the proposed by Gyrocode.com in their JSFiddle

当所有部分都具有相同的标签(如 <部分>)或在本例中具有相同的 class 名称(.scrollspy),这些部分告诉我们它们的 ID(作为插件的一部分)

我分享我的实现:

var menuSelected = null; // var to detect current selected element to pass the class that does visible the spy.

jQuery(document).ready(function( $ ){
  // Detect Initial scroll position
  var currentTop = $(window).scrollTop();

  $('.scrollspy').each(function (i) {
    var position = $(this).position();
    // Only to activate the top element ( current # ) 
    // if current is less than height.
    if ( i === 0 && !menuSelected && currentTop < $(this).height() ) navUpdate( $('a[href="#' + $(this).attr( 'id' ) + '"]') );

    // Basic implementation
    $(this).scrollspy({
      min: position.top - 100,
      max: position.top + $(this).height(),
      onEnter: function (element, position) {
        // update the button that have the element ID
        navUpdate( $('a[href="#' + element.id+ '"]') );
      }
    });
  });

  // method to update the navigation bar
  function navUpdate( where ){        
    if ( menuSelected ) menuSelected.removeClass( 'active' );
    menuSelected = where.parent();
    menuSelected.addClass( 'active' );
  }
});

纯javascript。 (主脚本50行↓)

要点:

  1. window.scrollY:获取文档当前垂直滚动的像素数。
  2. Element.offsetTop:获取当前元素外边框相对于top
  3. 内边框的距离

<style>
  body {
    min-height: 150em
  }
  article {
    min-height: 20em
  }

  .active {
    color: #fff307;
  }
</style>
<nav style="position: fixed; top:0; right: 50%">
  <ul>
    <li><a href="#about">about</a></li>
    <li><a href="#product">product</a></li>
    <li><a href="#contact">contact</a></li>
  </ul>
</nav>
<body>
  <article id="about" style="background-color: #a6b4cd">About</article>
  <article id="product" style="background-color: #eeb554">Product</article>
  <article id="contact" style="background-color: #88f3d1">Contact</article>
</body>

<script>
  //  main script
  /***
   * @param {Element} scrollTarget
   * @param {Element} labelTarget
   * @param {?Number} frequency : Number (millisecond) Control how often to do the check.
   */
  function ScrollSpy(scrollTarget, labelTarget, {frequency = 500}) {

    const labelTargets = [...labelTarget.querySelectorAll(`a[href^="#"]`)]
      .map(e => {
        const m = e.href.match(/.*#(.*)/)
        if (m) {
          return [e, m[1]]
        }
        return null
      }).filter(e => e !== null)

    const hrefArray = labelTargets.map(([e, href]) => href)

    // dataArray: [{targetElem, labelElem, id}, ...]
    const dataArray = [...scrollTarget.querySelectorAll(`[id]`)].map(e => {
      if (hrefArray.includes(e.id)) {
        return [e, ...labelTargets.filter(([_, href]) => href === e.id)[0]]
      }
      return null
    }).filter(e => e !== null)

    document.addEventListener("scroll", (e) => {
      if (Date.now() - ScrollSpy.lastChangeTime < frequency) {
        return
      }
      ScrollSpy.lastChangeTime = Date.now()

      for (const [curElem, labelElem, curID] of dataArray) {
        if (
          window.scrollY >= curElem.offsetTop &&
          window.scrollY <= curElem.offsetTop + curElem.clientHeight
        ) {
          labelElem.classList.add("active")
          continue
        }
        labelElem.classList.remove("active")
      }
    })
  }

  ScrollSpy.lastChangeTime = 0 // Create a new attribute to keep the variable.
</script>

<script>
  //  usage
  ScrollSpy(document.body, document.querySelector(`nav`), {})
  // ScrollSpy(document.body, document.querySelector(`nav`), {frequency: 1000})
</script>