效果圖

實(shí)現(xiàn)過程
因?yàn)樯梢患?jí)導(dǎo)航菜單我在另外一篇文章里寫過,本文會(huì)省略一些重復(fù)的東西,需要查看的請(qǐng)移步自動(dòng)生成右側(cè)導(dǎo)航欄,頁面滾動(dòng)時(shí)標(biāo)簽高亮。
1、html頁面結(jié)構(gòu)
<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>風(fēng)雨哈佛路</h4>
<h4>泰坦尼克號(hào)</h4>
<p>肖申克的救贖</p>
</div>
<div class="right-nav">
<p>導(dǎo)航</p>
<div id="nav"></div>
</div>
2、自動(dòng)生成導(dǎo)航欄
根據(jù)頁面中的h2和h4標(biāo)簽生成導(dǎo)航目錄。
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; //記錄該一級(jí)菜單下的二級(jí)菜單的個(gè)數(shù)
el.id = id;
//生成一級(jí)目錄
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) { //找到當(dāng)前的h2標(biāo)簽
element = element.nextElementSibling;
}
//生成二級(jí)目錄
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、頁面滾動(dòng)導(dǎo)航標(biāo)簽高亮
滾動(dòng)條滾動(dòng)到不同內(nèi)容塊時(shí)相應(yīng)的導(dǎo)航標(biāo)簽高亮。
$(function(){
$(window).scroll(function(){
var wst = $(window).scrollTop(); //滾動(dòng)條距離頂部距離頁面頂端的值
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、點(diǎn)擊導(dǎo)航標(biāo)簽時(shí)高亮
$('#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)
});
至于這里為什么會(huì)使用一個(gè)延時(shí)函數(shù),你可以把函數(shù)去掉看看效果?
是因?yàn)辄c(diǎn)擊標(biāo)簽發(fā)生頁面間的跳轉(zhuǎn),滾動(dòng)條的位置發(fā)生變化,又會(huì)觸發(fā)$(window).scroll()函數(shù),但是經(jīng)過該函數(shù)自動(dòng)計(jì)算出的標(biāo)簽并不是點(diǎn)擊的標(biāo)簽,所以需要加一個(gè)延時(shí)函數(shù),讓點(diǎn)擊事件的響應(yīng)函數(shù)結(jié)果覆蓋掉滾動(dòng)條滾動(dòng)事件的函數(shù)效果。
在下才疏學(xué)淺,只能想到這樣的解決方案了,如有大神指路,不勝感激~
源碼
這個(gè)頁面的完整代碼是:
<!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>風(fēng)雨哈佛路</h4>
<h4>泰坦尼克號(hào)</h4>
<p>肖申克的救贖</p>
</div>
<div class="right-nav">
<p>導(dǎo)航</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、創(chuàng)建右側(cè)導(dǎo)航欄*/
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; //記錄該一級(jí)菜單下的二級(jí)菜單的個(gè)數(shù)
// 1.1 生成一級(jí)目錄
html.push('<li><a href="#'+ id + '" id="'+ 'a' + i + i +'">' + (i + 1) + '.' + el.innerHTML + '</a></li>');
// 1.2 生成二級(jí)目錄
/* 生成二級(jí)目錄需要從兩個(gè)h2標(biāo)簽中找到所有的h4標(biāo)簽*/
var parent = h2[i].parentElement;
var element = h2[i];
while(1) {
if( (element == parent.lastElementChild) || (element == h2[i+1])) {
break; //搜索結(jié)束
}
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、點(diǎn)擊時(shí)激活右側(cè)導(dǎo)航*/
$('#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、滾動(dòng)時(shí)激活右側(cè)導(dǎo)航 */
$(function(){
$(window).scroll(function(){
var wst = $(window).scrollTop(); //滾動(dòng)條距離頂部距離頁面頂端的值
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>
不想復(fù)制的可以去我的github上下載,送免費(fèi)飛機(jī)票,如果喜歡,不妨star一下吧。
后話
工作快三個(gè)月了,學(xué)習(xí)的熱情也有點(diǎn)降低。多寫點(diǎn)文章不僅可以記錄遇到的問題,方便以后查看,還可以督促自己學(xué)習(xí),不失為一個(gè)保持學(xué)習(xí)熱情的好方法,如果有好方法的話還請(qǐng)不吝賜教。