マウスホイールで切り替わる全画面コンテンツをつくってみた

マウスホイールで切り替わる全画面コンテンツをつくってみた

マウスホイールで切り替わる全画面表示のコンテンツをつくってみました。
マウスホイールに反応して、次のページがフェードインしてくるようにしています。
スマホの場合は上下のフリックで切り替わるようにしました。
まずはデモをご確認ください。

デモ

コードと解説

html

<div class="contents page1 show">1</div>
<div class="contents page2">2</div>
<div class="contents page3">3</div>
<div class="contents page4">4</div>
<div class="contents page5">5</div>
<div class="contents page6">6</div>
<div class="contents page7">7</div>
<div class="contents page8">8</div>
<div class="contents page9">9</div>
<div class="contents page10">10</div>

10個のコンテンツを用意しました。

.show というクラスを付け外しすることで、コンテンツを切り替えます。
一番最初のコンテンツはあらかじめ .show を付けておき、表示させておきます。

css

body {
	position: relative;
	width: 100%;
	height: 100vh;
	margin: 0;
	padding: 0;
}
.contents {
	width: 100%;
	height: 100vh;
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	opacity: 0;
	transition: 1s;
	text-align: center;
	line-height: 100vh;
}

.page1 { background-color: aquamarine;}
.page2 { background-color: lightsalmon;}
.page3 { background-color: wheat;}
.page4 { background-color: cornflowerblue;}
.page5 { background-color: gold;}
.page6 { background-color: olive;}
.page7 { background-color: khaki;}
.page8 { background-color: orange;}
.page9 { background-color: gainsboro;}
.page10 { background-color: yellow;}

.show {
	opacity: 1;
}

body にposition: relative; を入れておきます。

.contents に各コンテンツのスタイルを指定。
幅・高さを画面いっぱいに。
position: absolute; で画面固定。
opacity: 0; にしておき、あらかじめ非表示とします。
transition: 1s; を入れ、フェードインのアニメーションするように。

.show に opacity: 1; を入れ、この .show を付け外しすることでコンテンツを入れ替えます。

javascript

var contents = document.querySelectorAll('.contents'); // コンテンツの取得
var count = 1; // 表示させるコンテンツの番号を設定

// スマホの場合、タッチスライドで動かす
if ((navigator.userAgent.indexOf('iPhone') > 0 && navigator.userAgent.indexOf('iPad') === -1) || navigator.userAgent.indexOf('iPod') > 0 || navigator.userAgent.indexOf('Android') > 0) {
	// タッチの位置を取得するための変数
	var touchStart,
		touchMove,
		touchDistance;
	
	// タッチし始めた位置
	window.addEventListener('touchstart', function (e) {
		touchStart = event.touches[0].pageY;
		touchMove = event.touches[0].pageY;
	});
	// タッチし、動かした位置
	window.addEventListener('touchmove', function (e) {
		touchMove = event.touches[0].pageY;
	});
	// タッチ終了時に
	window.addEventListener('touchend', function (e) {
		// タッチの開始位置から、移動後の位置を引く
		touchDistance = touchStart - touchMove;
		
		// タッチスライドが上方向だったら
		if (touchDistance > 70) {
			// countの値をプラス
			count++;
			// countの値の上限をコンテンツの数にする
			if (count >= contents.length) {
				count = contents.length;
			}
		}
		// タッチスライドが下方向だったら
		else if (touchDistance < -70) {
			// countの値をマイナス
			count--;
			// countの値の下限を1とする
			if (count <= 1) {
				count = 1;
			}
		}
		// タッチスライドがなかったら、何もしない
		else {
			
		}
		
		// 一旦コンテンツを全部非表示にして
		for (var i = 0; i < contents.length; i++) {
			contents[i].classList.remove('show'); // showクラスを削除して非表示に
		}
		// 該当のコンテンツのみ表示
		contents[count - 1].classList.add('show'); // showクラスを付与して表示
	});
}
// PCの場合、ホイールで動かす
else {
	var countFlg = false; // ホイールのイベントをやたらめったに取得しないためのフラグ
	
	// ホイールの動きがあったら
	window.addEventListener('wheel', function (e) {
		// countFlgがfalseの場合だけ動く
		if (!countFlg) {
			// ホイールが下方向だったら
			if (e.deltaY > 0) {
				// countの値をプラス
				count++;
				// countの値の上限をコンテンツの数とする
				if (count >= contents.length) {
					count = contents.length;
				}
			}
			// ホイールが上方向だったら
			else if (e.deltaY < 0) {
				//countの値をマイナスにする
				count--;
				// countの値の下限を1とする
				if (count <= 1) {
					count = 1;
				}
			}
			// countFlgをtrueにする
			countFlg = true;
			
			// 数秒後、countFlgをfalseにして、またホイールのイベントで動くように
			setTimeout(function () {
				countFlg = false;
			},1000 ); // 秒数を指定。ミリ秒

			// 一旦コンテンツを全部非表示にし、
			for (var i = 0; i < contents.length; i++) {
				contents[i].classList.remove('show'); // showクラスを削除して非表示に
			}
			// 該当コンテンツのみ表示
			contents[count - 1].classList.add('show'); // showクラスを付与して表示
		}
	});
}

スマホの場合は上下のフリックで、PCの場合はマウスホイールで反応させます。

スマホはフリックで

まずはスマホの場合。
touchstart でタッチを開始した位置を記録。
touchmove でタッチして移動した位置を記録。
touchend でタッチが離れたときに、touchstart(タッチの開始位置)からtouchmove(タッチして移動した位置)を引き算。移動距離を測ります。
上方向に動いたらcountの数値をプラス、下方向に動いたらマイナス。
一旦全コンテンツから .show を削除し非表示。
コンテンツの count番目に .show を付与して表示させます。
このときtransition: 1s; が効いているので、フェードインのアニメーションになります。

スマホの場合のポイント

touchstart でタッチを開始した時点で、
touchstart(タッチを開始した位置)と一緒に、touchmove(タッチして移動した位置)にもタッチを開始した位置を代入しておきます。
これをしておかないと、二回目のタッチの時に、ひとつ前の touchmove の値が残ってしまい、正しく動いてくれません。

PC時のホイールでの制御

wheelイベントで、マウスホイールの動きを取得。
event.deltaYの移動距離が上方向か下方向かで、countの値とプラスもしくはマイナス。
一旦全コンテンツから .show を削除し非表示に。
count番目のコンテンツに .show を付与して表示させます。

PCホイール取得時のポイント

何も気にせずやってしまうと、マウスホイールをぐりぐりっとたくさん動かしたときに、countの値をたくさん変化してしまいます。
なので一回目のホイールの動きだけを検知しするようにします。
countFlg という変数を用意。これが false の時だけホイールが反応するようにします。
反応したら countFlg を true にします。
setTimeout を使用し、trueになってから1秒後に countFlg を false に戻しています。

バリエーション

cssを変更するだけで、いろんな表示の仕方が可能です。
たとえば、フェードインしながら下からせり上がってくるようなバージョンを作ってみました。
以下、デモです。

せり上がりバージョンデモ

css

cssだけ変更をしています。

body {
	position: relative;
	width: 100%;
	height: 100vh;
	margin: 0;
	padding: 0;
	overflow: hidden;
}
.contents {
	width: 100%;
	height: 100vh;
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, 100%);
	opacity: 0;
	transition: 1s;
	text-align: center;
	line-height: 100vh;
}

.page1 { background-color: aquamarine;}
.page2 { background-color: lightsalmon;}
.page3 { background-color: wheat;}
.page4 { background-color: cornflowerblue;}
.page5 { background-color: gold;}
.page6 { background-color: olive;}
.page7 { background-color: khaki;}
.page8 { background-color: orange;}
.page9 { background-color: gainsboro;}
.page10 { background-color: yellow;}

.show {
	transform: translate(-50%, -50%);
	opacity: 1;
}

.contents に transform: translate(-50%, 100%); を追加。
あらかじめ画面の下の外に配置しておきます。

.show に transform: translate(-50%, -50%); を追加。
.show が付与されて表示されるときに、位置を画面内に持ってきます。