JavaScript:スワイプカウンター

JavaScript

右スワイプで+1加算、左スワイプで-1減算、ダブルタップでリセットという機能のJavaScriptで作ったスワイプカウンターです。
カウンター数値はローカルストレージに保存しているので、次回起動したときは前回の数値が表示されます。

実行イメージ

Chromeの開発者モードF12で実行

管理人補足

このカウンターは実は以前作ったプログラムがうまく動作しない場面があることが判明したため、作り直したものです。
使っているとスワイプしていないのにタップしただけで増減が発生してしまいました。

以前作った駄目なスワイプカウンター

touchendイベントにスワイプした距離をチェックする部分を追加したらうまく動作するようになりました。(以下ハイライト部分)

element.addEventListener("touchend", function(e) {
	// スワイプ終了時のxy座標を取得
	endX = e.changedTouches[0].pageX;
	endY = e.changedTouches[0].pageY;

	// 設定した距離より短い場合は処理をキャンセル
	if(Math.abs(startX - endX) < dist){
		console.log("スワイプキャンセル");
		return;
	}
		:
		:
}

ソースコード

スワイプの判定に関する解説は以前の記事をご覧ください。

index.html

<!DOCTYPE html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width,user-scalable=yes">
	<title>swipe counter</title>
	<link rel="stylesheet" href="style.css">
	<script src="main.js" type="text/javascript"></script>
</head>
<body>
	<header>
		<h1>swipe counter</h1>
	</header>
	
	<div id="contents">
		<p id="number"></p>
	</div>

	<footer><small>&copy; 2022 dianxnao.com</small></footer>
</body>
</html>

style.css

/* style.css */
@charset "utf-8";

*{
	margin: 0;
	padding: 0;
}
body{
	-webkit-text-size-adjust: none;	/* iPhoneのSafariで左上が拡大されて表示される場合の対処 */
	font-family: 'メイリオ', Helvetica;
	font-size: 16pt;
	width: 100%;
	margin: 0 auto;
}
header{
	padding: 1em;
	background-color: teal;
}
header h1{
	font-size: 16pt;
	text-align: center;
	color: white;
}
#contents{
	background-color: whitesmoke;
	text-align: center;
}
#number{
	padding: 0.5em 0;
	font-family: Impact, Helvetica;
	font-weight: 900;
	font-size: 128pt;
}
p{
	font-size: 12pt;
}
a{
	text-decoration: none;
}
footer{
	font-size: 0.8em;
	padding: 1em;
	text-align: center;
	color: white;
	background-color: teal;
}

@media screen and (min-width: 768px) and (max-width: 1024px) {
 
    /* タブレット用のcssを記述 */
	header h1{
		font-size: 20pt;
	}
	#contents{
		background-color: white;
		text-align: center;
	}
	#number{
		padding: 1em 0;
		font-family: Impact, Helvetica;
		font-weight: 900;
		font-size: 128pt;
	}
	p{
		font-size: 18pt;
	}
 
}

main.js

/* 
 * main.js
 *		左右スワイプでカウンター増減、ダブルタップでリセット
 *		スワイプ時にローカルストレージに数値を保存
 *
 */

/*
 * グローバル変数
 */
let count;							// カウンター数値格納用
let number;							// 表示部分のDOM取得用						
const STORAGE_KEY = "COUNTER";		// ローカルストレージキー

/*
 * スワイプイベント設定
 */
function setSwipe(elem) {
	const dist = 50;	// スワイプを感知する最低距離(ピクセル単位)

	let t = document.querySelector(elem);	// イベント対象
	let startX, startY;	// スワイプ開始時 xy座標
	let moveX, moveY;	// スワイプ中 xy座標
	let endX, endY;		// スワイプ終了時 xy座標
	let tapCount = 0;	// ダブルタップカウント用

	// スワイプ開始時
	t.addEventListener("touchstart", function(e) {
		// スマホのデフォルト動作をキャンセル
		e.preventDefault();
		// xy座標を取得
		startX = e.touches[0].pageX;
		startY = e.touches[0].pageY;

		// ダブルタップでリセット
		if(tapCount === 0){
			tapCount++;

			// 300ミリ秒以内にタップしたらダブルタップ扱いとする
			setTimeout( () => {
				tapCount = 0;
			}, 300);
		}
		else{
			tapCount = 0;
			reset();
		}

	});
	
	// スワイプ中
	t.addEventListener("touchmove", function(e) {
		tapCount = 0;	// 素早くスワイプするとダブルタップ扱いになるため必要
		// スマホのデフォルト動作をキャンセル
		e.preventDefault();
		// xy座標を取得
		moveX = e.changedTouches[0].pageX;
		moveY = e.changedTouches[0].pageY;
	});
	
	// スワイプ終了時: スワイプした距離から左右どちらにスワイプしたかを判定する/距離が短い場合何もしない
	t.addEventListener("touchend", function(e) {
		// スワイプ終了時のxy座標を取得
		endX = e.changedTouches[0].pageX;
		endY = e.changedTouches[0].pageY;

		// 設定した距離より短い場合は処理をキャンセル
		if(Math.abs(startX - endX) < dist){
			console.log("スワイプキャンセル");
			return;
		}

		// 左 <=== 右 スワイプ
		if (startX > moveX && startX - dist > moveX) {
			sub();	// 数値を-1する
		}
		// 左 ==> 右 スワイプ
		else if (startX < moveX && startX + dist < moveX) {
			add();			// 数値を+1する
		}
		/*
		else if(startY < moveY && startY + dist < moveY){ 	// 下方向にスワイプ
			reset();
		}
		*/
	});
}

/*
 * ローカルストレージチェックし、前回最後に表示していた数値データを取得
 */
function checkStorageKey(){
	// ローカルストレージチェック
	let ret = localStorage.getItem(STORAGE_KEY);
	console.log("保存状態: " + ret);
	
	// キーが存在するかのチェック
	if(ret !== null){		// 戻り値がnull:保存データあり
		count = Number(ret);	// 数値化して変数に代入(ローカルストレージデータは文字列のため計算できるようにする)
	}
	else{						// 戻り値が存在:保存データなし
		count = 0;				// カウンターに0を代入
	}
	console.log("count = " + count);
}

/*
 * ローカルストレージに現在表示中の番号を保存
 */
function setStorageKey(){
	localStorage.setItem(STORAGE_KEY, count);
}

/*
 * 数値を+1する
 */
function add(){
	count ++;
	setNumber();	// 表示とローカルストレージ保存
}

/*
 * 数値を-1する
 */
function sub(){
	count --;
	setNumber();	// 表示とローカルストレージ保存
}

/*
 * 数値を0にリセット
 */
function reset(){
	let ret = confirm("リセットしますか?");
	
	if(ret === true){
		count = 0;
		setNumber();	// 表示とローカルストレージ保存
	}
}

/*
 * 数値を画面に表示後、ローカルストレージに保存
 */
function setNumber(){
	// 数値を表示
	number.innerHTML = count;
	// ストレージに表示中の数値を保存
	setStorageKey();
}

/*
 * 起動時の処理
 */
window.addEventListener("load", function(){
	// 数値表示部分のDOM取得
	number = document.getElementById("number");
		
	// ローカルストレージをチェック
	checkStorageKey();

	// 数値を画面に表示
	setNumber();

	// スワイプイベント設定
	setSwipe("#contents");
});

コメント

タイトルとURLをコピーしました