記事全体の読んだ分量を示すバーをつくる

記事全体の読んだ分量を示すバーをつくる

最近メディアサイトなどでよく見かけて、ユーザービリティ的にいいなあと思ったのでつくってみました。
まずはデモをご確認ください。

デモ

考え方

記事部分の高さを取得。
それを1000分の1ずつにわける。
スクロール量が記事の高さの1000分の1進むごとに、バーが0.1%ずつ進んでいく。

コード解説

htmlとcss

<div id="meter">
	<div id="meterInner"></div>
</div>    
<div id="contents">
        コンテンツが入ります。<br>
        コンテンツが入ります。
</div>
#meter {
	height: 3px;
	width: 100%;
	transition: .5s;
	position: fixed;
}

#meterInner {
	background-color: black;
	width: 100%;
	height: 3px;
	position: absolute;
	left: -100%;
}

#contents {
	background-color: lightgray;
}

#meter は、記事全体の分量を示す部分。高さ3px横幅いっぱいのバーとしました。
transition: .5s; を入れて、バーの動きをなめらかにするようにしています。
位置はfixedにしました。

#meterInner は、読んだ分量を示す色付きのバー。色を黒にしています。
あらかじめ left: -100%; としておきます。
読んだ分量に応じてこの #meterInner の位置を右へずらしていくことでバーを進ませます。

#contents は記事部分です。

javascript

var meter = document.getElementById('meterInner'); // 読んだ分量を示すバー
var contents = document.getElementById('contents'); // 記事部分を取得
var contentsHeight = contents.clientHeight - window.innerHeight; // 記事部分の高さ

var windowY = window.pageYOffset; // スクロール位置を取得
var contentsRect = contents.getBoundingClientRect(); // 記事が始まる位置
var contentsY = contentsRect.top + windowY; // 記事が始まる位置

var volume = contentsY; // 記事の分量を入れるための変数。初期値は記事の開始位置
var volumes = []; // 記事の分量を入れるための配列

for (var i = 0; i < 1000; i++) { // 1000回ループ
	volumes.push(volume); // 配列volumesにvolumeを入れる。初期値は記事の開始位置
	volume += contentsHeight / 1000; // 記事の高さを1000分の1したものをvolumeにプラス。
}

// スクロールすると
window.addEventListener('scroll', function() {
	// スクロール位置を取得
	windowY = window.pageYOffset;
	
	for (var i = 0; i < volumes.length; i++) {
		// スクロール位置が記事分量の1000分の1に達するごとに、分量を示すバーを0.1%ずつ右に移動させる
		if(windowY > volumes[i]) {
			meter.style.transform = 'translate('+ i / 10 +'%, 0)';
		}
	}
});

記事部分の高さを取得。それを1000分の1にして配列に入れる。
配列の1番目は記事の開始位置とする。

スクロールがあるたびに、記事部分の高さを1000分の1ずつにした配列それぞれに達したか調べて、達するごとに
css の transform の translate で0.1%ずつ右へずらしていきます。

使い方

それぞれコピペしてもらえれば動くと思います。
任意でバーの色をcssで変えてもらったり、記事本文にあたる#contentsのidやclass名に応じてjsのソースも変更してもらえればOKです!