美文网首页
自动生成二级菜单的导航栏,页面滚动高亮

自动生成二级菜单的导航栏,页面滚动高亮

作者: wuyadream | 来源:发表于2017-09-22 18:06 被阅读0次

    效果图

    img_1.png

    实现过程

    因为生成一级导航菜单我在另外一篇文章里写过,本文会省略一些重复的东西,需要查看的请移步自动生成右侧导航栏,页面滚动时标签高亮

    1、html页面结构

    <div class="content" id="article">
        <h2>美食</h2>
        <h4>鱼香肉丝</h4>
        <h4>油焖小龙虾</h4>
        <p>酸菜鱼</p>
        <h2>人文</h2>
        <h4>蜀绣</h4>
        <p>陶瓷</p>
        <h4>丝绸</h4>
        <p>油画</p>
        <h2>影视</h2>
        <h4>风雨哈佛路</h4>
        <h4>泰坦尼克号</h4>
        <p>肖申克的救赎</p>
    </div>
    <div class="right-nav">
        <p>导航</p>
        <div id="nav"></div>
    </div>
    

    2、自动生成导航栏

    根据页面中的h2和h4标签生成导航目录。

                    var html = ['<ul>'];
                    var headings = document.querySelectorAll('#article h2');
                    for(var i = 0; i < headings.length; i++) {
                        var id = 'd' + i;
                        var el = headings[i];
                        var title2_num = 0; //记录该一级菜单下的二级菜单的个数
                        el.id = id;
    
                        //生成一级目录
                       html.push('<li><a href="'+el.childNodes[1].href+ '" id = "'+'a' + i + i+'">'+(i+1)+'. '+el.firstChild.nodeValue+'</a>');
    
                       var parent = headings[i].parentElement.parentElement;
                       var element = parent.firstElementChild;
                       while(element != headings[i].parentElement) {  //找到当前的h2标签
                           element = element.nextElementSibling;
                       }
    
                       //生成二级目录
                      while(1){
                          if( (element == parent.lastElementChild) || ((i<headings.length-1) &&(element == headings[i+1].parentElement))) {
                              // console.log('break');
                              break;
                          }
                          element = element.nextElementSibling;
                          var level2_title = element.querySelectorAll('h4');
                          var len = 0;
                          for(len=0; len< level2_title.length; len++){
                              level2_title[len].id = 'd'+i + ''+title2_num;
                              html.push('<li><a href="#' +level2_title[len].id+ '" id = "a' +i +''+ i+ ''+ title2_num +''+ 
                                   title2_num+ '" class="level2_a">'+(i+1)+'.'+(title2_num+1)+' '
                                   +level2_title[len].firstChild.nodeValue+'</a></li>');
                          }
                          title2_num = title2_num + level2_title.length;
                       }
                        level2_title_length.push(title2_num);
                    }
                    var nav = document.getElementById('nav');
                    nav.innerHTML = html.join('\n');
    

    3、页面滚动导航标签高亮

    滚动条滚动到不同内容块时相应的导航标签高亮。

     $(function(){
                    $(window).scroll(function(){
                        var wst = $(window).scrollTop(); //滚动条距离顶部距离页面顶端的值
                        var title = document.querySelectorAll('#article h2');
                        for(var i=0; i<title.length; i++){
                            if($("#d"+i).offset().top <= wst){
                                $('#nav a').removeClass("c");
                                $('#a'+i+i).addClass("c");
                            }
                            for(var j=0; j<level2_title_length[i];j++){
                                if($("#d"+i+j).offset().top <= wst){
                                    $('#nav a').removeClass("c");
                                    $('#a'+i+i+j+j).addClass("c");
                                }
                            }
                        }
                    });
    
                });
    

    4、点击导航标签时高亮

                    $('#nav a').click(function(e){
                        setTimeout(function(){
                            $('#nav a').removeClass("c");
                            $(this).addClass("c");
                            if( e.target.getAttribute("class") == null) {
                                e.target.setAttribute("class", "c");
                            } else {
                                e.target.setAttribute("class", e.target.getAttribute("class")+ ' '+"c");
                            }
                        },0)
                    });
    

    至于这里为什么会使用一个延时函数,你可以把函数去掉看看效果?
    是因为点击标签发生页面间的跳转,滚动条的位置发生变化,又会触发$(window).scroll()函数,但是经过该函数自动计算出的标签并不是点击的标签,所以需要加一个延时函数,让点击事件的响应函数结果覆盖掉滚动条滚动事件的函数效果。
    在下才疏学浅,只能想到这样的解决方案了,如有大神指路,不胜感激~

    源码

    这个页面的完整代码是:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>anchor-nav</title>
        <style>
            html, body {
                width: 100%;
                height: 100%;
                box-sizing: border-box;
                text-align: center;
            }
            .content {
                width:800px;
                margin: 0 auto;
                margin-top: 100px;
            }
            .content h2 {
                font-size: 18px;
                color:rgba(0,0,0,.87);
                height: 600px;
                line-height: 600px;
                background-color: deepskyblue;
            }
            .content h4 {
                font-size: 16px;
                color:rgba(0,0,0,.87);
                background-color: lightskyblue;
                height: 400px;
                line-height: 400px;
    
            }
            .content p{
                font-size: 12px;
                color:#666;
                height: 400px;
                line-height: 400px;
                background-color: skyblue;
            }
            .right-nav {
                position: fixed;
                right:20px;
                top:200px;
                width: 200px;
                text-align: left;
            }
    
            .right-nav p {
                color:#333;
            }
    
            .right-nav ul {
                padding-left: 0;
            }
    
            .right-nav li{
                list-style: none;
    
            }
            .right-nav a {
                color:#999;
                padding-left:6px ;
                border-left: 2px solid #999;
                display: inline-block;
                margin-bottom: 4px;
                text-decoration: none;
            }
    
            .right-nav .level2_a {
                color:#999;
                padding-left:20px ;
                border-left: 2px solid #999;
            }
    
            .right-nav a:hover{
                color:#2277da;
            }
    
            .right-nav .c{
                border-left: 2px solid #2277da;
                color:#2277da;
            }
    
        </style>
    </head>
    <body>
    <h1>anchor-nav</h1>
    <div class="content" id="article">
        <h2>美食</h2>
        <h4>鱼香肉丝</h4>
        <h4>油焖小龙虾</h4>
        <p>酸菜鱼</p>
        <h2>人文</h2>
        <h4>蜀绣</h4>
        <p>陶瓷</p>
        <h4>丝绸</h4>
        <p>油画</p>
        <h2>影视</h2>
        <h4>风雨哈佛路</h4>
        <h4>泰坦尼克号</h4>
        <p>肖申克的救赎</p>
    </div>
    <div class="right-nav">
        <p>导航</p>
        <div id="nav"></div>
    </div>
    
    <script type="text/javascript" src="jquery-1.11.3.min.js"></script>
    <script>
    
        var h4_length = [];
        window.onload = function () {
    
            /* 1、创建右侧导航栏*/
            var html = ['<ul>'];
            var h2 = document.querySelectorAll('#article h2');
            for(var i = 0; i < h2.length; i++) {
                var id = 'd' + i;
                var el = h2[i];
                el.id = id;
                var h4_num = 0; //记录该一级菜单下的二级菜单的个数
    
                // 1.1 生成一级目录
                html.push('<li><a href="#'+ id + '" id="'+ 'a' + i + i +'">' + (i + 1) + '.' + el.innerHTML + '</a></li>');
    
                // 1.2 生成二级目录
                /* 生成二级目录需要从两个h2标签中找到所有的h4标签*/
                var parent = h2[i].parentElement;
                var element = h2[i];
                while(1) {
                    if( (element == parent.lastElementChild) || (element == h2[i+1])) {
                        break; //搜索结束
                    }
                    element = element.nextElementSibling;
                    // console.log(element.tagName.toLowerCase());
                    if(element.tagName.toLowerCase() == 'h4') {
                        element.id = 'd' + i + h4_num;
                        html.push('<li><a href="#' + element.id + '" id="a' + i + '' + i + ''+ h4_num + '' + h4_num + '" class="level2_a">' + (i+1) + '.' + (h4_num+1)+ ' '+element.innerText + '</a></li>');
                        h4_num = h4_num + 1;
                    }
                }
                h4_length.push(h4_num);
            }
            html.push('</ul>');
            var nav = document.getElementById('nav');
            nav.innerHTML = html.join('\n');
    
            /* 2、点击时激活右侧导航*/
            $('#nav a').click(function(e){
                setTimeout(function(){
                    $('#nav a').removeClass("c");
                    if( e.target.getAttribute("class") == null) {
                        e.target.setAttribute("class", "c");
                     } else {
                       e.target.setAttribute("class", e.target.getAttribute("class")+ ' '+"c");
                    }
                },0);
            });
    
        }
    
        /* 3、滚动时激活右侧导航 */
        $(function(){
            $(window).scroll(function(){
                var wst = $(window).scrollTop(); //滚动条距离顶部距离页面顶端的值
                var h2 = document.querySelectorAll('#article h2');
                for(var i=0; i<h2.length; i++){
                    if($("#d"+i).offset().top <= wst){
                        $('#nav a').removeClass("c");
    
                        if( !$('#a'+i+i).hasClass("c")) {
                            $('#a'+i+i).addClass("c");
                        }
                    }
                    for(var j = 0; j < h4_length[i]; j++){
                        if($("#d"+i+j).offset().top <= wst){
                            $('#nav a').removeClass("c");
                            $('#a'+i+i+j+j).addClass("c");
                        }
                    }
                }
            });
    
        });
    
    </script>
    </body>
    </html>
    

    不想复制的可以去我的github上下载,送免费飞机票,如果喜欢,不妨star一下吧。

    后话

    工作快三个月了,学习的热情也有点降低。多写点文章不仅可以记录遇到的问题,方便以后查看,还可以督促自己学习,不失为一个保持学习热情的好方法,如果有好方法的话还请不吝赐教。

    相关文章

      网友评论

          本文标题:自动生成二级菜单的导航栏,页面滚动高亮

          本文链接:https://www.haomeiwen.com/subject/klifextx.html