ページ内ナビをコンテンツの位置によってカレント表示させる

Javascript

パララックスをつかったサイトなど、縦長のページが昔に比べれば多くなった感じがしますがその際に、ページ内用のナビを設置する場合があると思います。スクロールした時そのコンテンツのエリアに来たら、ナビをカレント表示させるjsを調べて作ってみました。

参考にしたサイト

作ってみたと言いつつ、大部分が参考サイト通りなので先にご紹介いたします。

カレント表示でaタグはそのまま

とりあえずカレント表示されればOKのタイプ。カレントの箇所もクリックできます。

HTMLの抜粋は以下


<ul id="nav">
<li><a href="#section01">menu<a></li>
<li><a href="#section02">menu</a></li>
<li><a href="#section03">menu</a></li>
</ul>
</div>

<div class="box" id="section01">
<p>サンプルページ</p>
</div>

<div class="box" id="section02">
<p>サンプルページ<p>
</div>

<div class="box" id="section03">
<p>サンプルページ</p>
</div>

Javascriptはこちら


$(function(){
	var set = 300;//ウインドウ上部からどれぐらいの位置で変化させるか
	var boxTop = new Array;
	var current = -1;

	//各要素の位置
	$('.box').each(function(i) {
		boxTop[i] = $(this).offset().top;
	});
	//最初の要素にclass="on"をつける
	changeBox(0);
	//スクロールした時の処理
	$(window).scroll(function(){
		scrollPosition = $(window).scrollTop();
		for (var i = boxTop.length - 1 ; i >= 0; i--) {
			if ($(window).scrollTop() > boxTop[i] - set) {
	            changeBox(i);
	        	break;
	        }
		};
	});
	//ナビの処理
	function changeBox(secNum) {
		if (secNum != current) {
			current = secNum;
			secNum2 = secNum + 1;//HTML順序用
			$('#nav li').removeClass('on');
			$('#nav li:nth-child(' + secNum2 +')').addClass('on');

			/* 位置によって個別に処理をしたい場合 
			if (current == 0) {
				// 現在地がsection1の場合の処理
			} else if (current == 1) {
				// 現在地がsection2の場合の処理
			} else if (current == 2) {
				// 現在地がsection3の場合の処理
			}*/
		}
	};
});

基本的な仕組みは

  1. 各コンテンツ要素の位置を取得
  2. スクロールして、スクロールの位置が各要素の位置に来たらそれに付随するナビにclassをつける

です。ただその各コンテンツ要素の位置ぴったりでナビを切り替えると、ウインドウサイズによっては最後のコンテンツを見てるのにナビがその前のものを 指定したままになるなどあるので、数値を変えることによってナビを切り替える位置を調整出来ます。

カレント表示させてaタグも消す

次は先ほどのものからカレントになってるものからaタグを削除したものになります。


$(function(){
	var set = 300;//ウインドウ上部からどれぐらいの位置で変化させるか
	var boxTop = new Array;
	var boxNav = new Array;
	var current = -1;

	//各要素の位置
	$('.box').each(function(i) {
    	boxTop[i] = $(this).offset().top;
	});
	//ナビのhrefを取得
	$('#nav li a').each(function(t) {
		boxNav[t] = $(this).attr('href');
	});
	//最初の要素にclass="on"をつける
	changeBox(0);
	//スクロールした時の処理
	$(window).scroll(function(){
		scrollPosition = $(window).scrollTop();
		for (var i = boxTop.length - 1 ; i >= 0; i--) {
			if ($(window).scrollTop() > boxTop[i] - set) {
	            changeBox(i);
	        	break;
	        }
		};
	});
	//ナビの処理
	function changeBox(secNum) {
		if (secNum != current) {
			current = secNum;
			secNum2 = secNum + 1;//HTML順序用

			$('#nav li').removeClass('on');
			$('#nav li').contents().contents().unwrap('<a>');
			$('#nav li').contents().wrap('<a>')
			j = boxNav.length;
			for(var t = boxNav.length -1 ; t >= 0; t--){
				$('#nav li:nth-child(' + j +') a').attr('href',boxNav[t]);
				j--;
			};
			$('#nav li:nth-child(' + secNum2  +')').addClass('on').contents().contents().unwrap('<a>');

			/* 位置によって個別に処理をしたい場合 
			if (current == 0) {
				// 現在地がsection1の場合の処理
			} else if (current == 1) {
				// 現在地がsection2の場合の処理
			} else if (current == 2) {
				// 現在地がsection3の場合の処理
			}*/
		}
	}
});

太字になっている箇所が変更点です。aタグを消すとアンカーも消えてしまうので、最初にアンカーを配列にいれてaタグを追加するときに合わせて入れています。