精简jQuery滚动高亮代码

很久之前写过一个插件:jQuery滚动高亮插件:scrollHighlight,关于在滚动网页时同时高亮对应的导航链接节点。今天在CSS-trick上看到一个比较精简的代码,只有8行代码就搞定。

HTML

<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<div class="nav">
  <span id ="menu">&#9776;</span> 
  <ul id="top-menu">
    <li><a href="#one" class="links">Menu 1</a></li>
    <li><a href="#two" class="links">Menu 2</a></li>
    <li><a href="#three" class="links">Menu 3</a></li>
    <li><a href="#four" class="links">Menu 4</a></li>
    <li><a href="#five" class="links">Menu 5</a></li>
    <li><a href="#six" class="links">Menu 6</a></li>
  </ul>
</div>
<div id="wrapper">
  <div id="one" class="container">
    one
  </div>
  <div id="two" class="container">
    two
  </div>
  <div id="three" class="container">
    three
  </div>
  <div id="four" class="container">
    four
  </div>
  <div id="five" class="container">
    five
  </div>
  <div id="six" class="container">
    six
  </div>
</div>

JS代码:附带超详细的代码解释,实际上只有7-8行代码就搞定

$(document).ready(function(){
  // $sections incleudes all of the container divs that relate to menu items.
  var $sections = $('.container');
  
  // The user scrolls
  $(window).scroll(function(){
    
    // currentScroll is the number of pixels the window has been scrolled
    var currentScroll = $(this).scrollTop();
    
    // $currentSection is somewhere to place the section we must be looking at
    var $currentSection
    
    // We check the position of each of the divs compared to the windows scroll positon
    $sections.each(function(){
      // divPosition is the position down the page in px of the current section we are testing      
      var divPosition = $(this).offset().top;
      
      // If the divPosition is less the the currentScroll position the div we are testing has moved above the window edge.
      // the -1 is so that it includes the div 1px before the div leave the top of the window.
      if( divPosition - 1 < currentScroll ){
        // We have either read the section or are currently reading the section so we'll call it our current section
        $currentSection = $(this);
        
        // If the next div has also been read or we are currently reading it we will overwrite this value again. This will leave us with the LAST div that passed.
      }
      
      // This is the bit of code that uses the currentSection as its source of ID
      var id = $currentSection.attr('id');
   	 $('a').removeClass('active');
   	 $("[href=#"+id+"]").addClass('active');
      
    })

  });
});

CSS代码就不写了。

直接看演示了:演示

评论里说到不了最后一个,在网上看到一个代码是支持获取滚动最底部的时候,当最后一个列表的元素没有高亮时,此时会移除其它元素的高亮,然后给最后一个元素高亮。

<div id="main">
    <div class="container clearfix">        
        <div id="sidebar">
            <div id="nav-anchor"></div>
            <nav>
                <ul>
                    <li><a href="#home">Home</a></li>
                    <li><a href="#about">About</a></li>
                    <li><a href="#services">Services</a></li>
                    <li><a href="#blog">Blog</a></li>
                    <li><a href="#contact">Contact</a></li>
                </ul>
            </nav>
        </div><!-- /sidebar -->
        <div id="content">
            <section id="home">
                ...
            </section>
            <section id="about">
                ...
            </section>
            <section id="services">
                ...
            </section>
            <section id="blog">
                ...
            </section>
            <section id="contact">
                ...
            </section>
        </div><!-- /#content -->
    </div><!-- /.container -->
</div><!-- /#main -->

JavaScript代码:

$(document).ready(function(){

    /** 
     * This part does the "fixed navigation after scroll" functionality
     * We use the jQuery function scroll() to recalculate our variables as the 
     * page is scrolled/
     */
    $(window).scroll(function(){
        var window_top = $(window).scrollTop() + 12; // the "12" should equal the margin-top value for nav.stick
        var div_top = $('#nav-anchor').offset().top;
            if (window_top > div_top) {
                $('nav').addClass('stick');
            } else {
                $('nav').removeClass('stick');
            }
    });

    /**
     * This part causes smooth scrolling using scrollto.js
     * We target all a tags inside the nav, and apply the scrollto.js to it.
     */
    $("nav a").click(function(evn){
        evn.preventDefault();
        $('html,body').scrollTo(this.hash, this.hash); 
    });

    /**
     * This part handles the highlighting functionality.
     * We use the scroll functionality again, some array creation and 
     * manipulation, class adding and class removing, and conditional testing
     */
    var aChildren = $("nav li").children(); // find the a children of the list items
    var aArray = []; // create the empty aArray
    for (var i=0; i < aChildren.length; i++) {    
        var aChild = aChildren[i];
        var ahref = $(aChild).attr('href');
        aArray.push(ahref);
    } // this for loop fills the aArray with attribute href values

    $(window).scroll(function(){
        var windowPos = $(window).scrollTop(); // get the offset of the window from the top of page
        var windowHeight = $(window).height(); // get the height of the window
        var docHeight = $(document).height();

        for (var i=0; i < aArray.length; i++) {
            var theID = aArray[i];
            var divPos = $(theID).offset().top; // get the offset of the div from the top of page
            var divHeight = $(theID).height(); // get the height of the div in question
            if (windowPos >= divPos && windowPos < (divPos + divHeight)) {
                $("a[href='" + theID + "']").addClass("nav-active");
            } else {
                $("a[href='" + theID + "']").removeClass("nav-active");
            }
        }

        if(windowPos + windowHeight == docHeight) {
            if (!$("nav li:last-child a").hasClass("nav-active")) {
                var navActiveCurrent = $(".nav-active").attr("href");
                $("a[href='" + navActiveCurrent + "']").removeClass("nav-active");
                $("nav li:last-child a").addClass("nav-active");
            }
        }
    });
});

演示 下载


关注我

我的微信公众号:前端开发博客,在后台回复以下关键字可以获取资源。

  • 回复「小抄」,领取Vue、JavaScript 和 WebComponent 小抄 PDF
  • 回复「Vue脑图」获取 Vue 相关脑图
  • 回复「思维图」获取 JavaScript 相关思维图
  • 回复「简历」获取简历制作建议
  • 回复「简历模板」获取精选的简历模板
  • 回复「加群」进入500人前端精英群
  • 回复「电子书」下载我整理的大量前端资源,含面试、Vue实战项目、CSS和JavaScript电子书等。
  • 回复「知识点」下载高清JavaScript知识点图谱

每日分享有用的前端开发知识,加我微信:caibaojian89 交流