コメントフォーム(承認式)

ホーム
プロフィール
製作物
前の記事
ISyntaxの使い方
次の記事
C++で現在時刻を任意フォーマットで出力する
投稿日時:2020/01/16 07:53、最終更新日時:2020/01/19 16:09

JavaScriptによるスムーズスクロール

  • pocket
  • はてなブックマーク

はじめに

 本ブログはIDへのリンクをクリックすると、そのIDの位置へとスムーズスクロールする。これはjQueryで実装していたが、jQueryをあまり使いたくなかったため、生のJavaScriptで実装することにした。

 おそらくCSSのscroll-behaviorを用いて実装することがもっとも簡単であると考えられるが、今回はJavaScriptの話であるため、扱わない。

ソースコード

 いきなり結論となるが、コードは以下のようになる。

	window.addEventListener('DOMContentLoaded', function() {
		// #で始まる全てのアンカーに対するスムーズスクロール
		const a_elements = document.querySelectorAll('a[href^="#"]');
		for (let i = 0, n = a_elements.length; i < n; ++i) {
			a_elements[i].onclick = function() {
				// URLが#でなければそのIDの位置へとジャンプ
				if (a_elements[i].getAttribute('href') != '#') {
					// 移動量(現在の画面のtopを0としてhrefの示すIDの位置の取得)
					const move = document.querySelector(a_elements[i].getAttribute('href')).getBoundingClientRect().top;
					// 現在のページのスクロール位置(どちらかが使えるはず)
					const top = document.documentElement.scrollTop || document.body.scrollTop;
					// 400msでスムーズスクロール(16msごとに描画更新)
					const start_time = (new Date()).getTime();
					const interval_id = setInterval(function() {
						// 現在の経過時間を取得
						var elapsed_time = (new Date()).getTime() - start_time;
						// 400msを超えたらインターバルの解除
						if (elapsed_time > 400) {
							clearInterval(interval_id);
							elapsed_time = 400;
						}
						// 線型補間で動かす
						window.scroll(0, top + move * (elapsed_time / 400));
					}, 16);
				}
				// URLが#ならばトップへとジャンプ
				else {
					// 上とほとんど同じ
					const top = document.documentElement.scrollTop || document.body.scrollTop;
					const start_time = (new Date()).getTime();
					const interval_id = setInterval(function() {
						var elapsed_time = (new Date()).getTime() - start_time;
						if (elapsed_time > 400) {
							clearInterval(interval_id);
							elapsed_time = 400;
						}
						window.scroll(0, top - top * (elapsed_time / 400));
					}, 16);
				}
				return false;
			};
		}
	});

 コメント通りであるため、特に解説は必要ないだろう。setIntervalの周期が16msであるのは描画レートである60FPSを意識している。これに対して改変を加えるとすれば、スクロールにかける秒数を変えたり、スクロール方法を線型補間ではなく緩急を付けてみたりするくらいだろう。

おわりに

 おそらくJavaScriptを用いて開発しているエンジニアの人から見れば常識的なのかもしれない(色々なサイトでスムーズスクロールを見かけるため)が、私自身はWeb系は素人もいいところなのでこれで満足である。


前の記事
ISyntaxの使い方
次の記事
C++で現在時刻を任意フォーマットで出力する

コメント欄(詳細な記述方法についてはこちら)

まだコメントの投稿はありません