【Javascript】Canvasに何かしら描画されているかどうか判定する方法を考えてみた

Javascript,開発

おはようございます。

何故か昨日も東京はあまり雨が降りませんでしたね。
嵐の前の静けさなのだろうか。

九州は災害級の大雨だそうで、心配ですね。被害が少なく済めばいいのですが。。

本題となりますが、
昨日に引き続き Canvas 関連の話し。

SignaturePad では、Canvasにサインが書かれているかどうかを isEmpty 関数にて簡単に判定できるようになっていますが、
Canvas 単体で判定する方法についてはなかなか見つかりませんでしたので、判定する方法を考えてみました。

プログラムは前回のものを流用します。

【Javascript】SignaturePad を使ってブラウザ上でサインを書けるようにする

スポンサーリンク

画面の修正

sampleSign.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta http-equiv="content-type" content="text/html; charset=UTF-8">
	<title>サンプルサイン</title>
	<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
	<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />
	<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.1/css/all.css">
	<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div class="wrapper" >
	<div style="margin: 20px;">
<pre>
Canvas のサンプル

signaturePad を使って簡単にサインを保存できます。
</pre>
	</div>
<div class="container container-fluid">
	<div class="row">
		<div calss="col-md-6">
			<table class="table table-borderd">
				<tr>
					<th>受領サイン:</th>
					<td style="text-align:right;">
						<div class="form-group">
							<label for="number" class="control-label col-md-2">文字色</label>
							<div class="col-md-2">
								<select class="form-control" id="color">
									<option value="black">黒</option>
									<option value="white">白</option>
									<option value="red">赤</option>
									<option value="blue">青</option>
									<option value="yellow">黄</option>
									<option value="green">緑</option>
								</select>
							</div>
							<label for="number" class="control-label col-md-2">背景色</label>
							<div class="col-md-2">
								<select class="form-control" id="bcolor">
									<option value="black">黒</option>
									<option value="white" selected>白</option>
									<option value="red">赤</option>
									<option value="blue">青</option>
									<option value="yellow">黄</option>
									<option value="green">緑</option>
								</select>
							</div>
							<label for="number" class="control-label col-md-2">線の太さ</label>
							<div class="col-md-2">
								<input class="form-control" type="text" placeholder="文字の太さ" value="3" id="weight">
							</div>
						</div>
					</td>
				</tr>
				<tr>
					<td colspan="2">
						<canvas id="sign" style="border: 2px solid;"></canvas>
					</td>
				</tr>
				<tr>
					<td colspan="2">
						<canvas id="sign2" style="border: 2px solid;"></canvas>
					</td>
				</tr>
				<tr>
					<td style="text-align:left; border-right:0px;">
						<button type="button" class="btn btn-info" id="checkButton">データチェック</button>
					</td>
					<td style="text-align:right;">
						<button type="button" class="btn btn-active" id="clearButton">クリア</button>
						<button type="button" class="btn btn-primary" id="saveButton">保存</button>
					</td>
				</tr>
			</table>
		</div>
	</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/signature_pad@2.3.2/dist/signature_pad.min.js"></script>
<script src="js/sampleSign.js"></script>
</body>
</html>

プログラムの修正

script/sampleSign.js

var signaturePad;
/**
 * ページ読み込み時の処理
 */
$(function(){

	// サイズ調整
	$("#sign").attr("width", $(".table").width() -20);
	$("#sign2").attr("width", $(".table").width() -20);
	
	// Canvasに描かれているオブジェクトのRGBA配列の値(0 ~ 255)を集計する
	var getRGBASummary = function () {
		var canvas = $("#sign").get(0);
		var image = canvas.getContext("2d").getImageData(0, 0, canvas.width, canvas.height);
		var data = image.data;
		var sum = data.reduce(function(prev, current, i, arr) { return prev+current; });
		return sum;
	};
	
	// Canvasの設定
	var setOptions = function () {
		signaturePad.penColor = $("#color").val();
		signaturePad.backgroundColor = $("#bcolor").val();
		signaturePad.minWidth = parseInt($("#weight").val());
		signaturePad.maxWidth = parseInt($("#weight").val());
		signaturePad.clear();
		console.log(signaturePad);

		// 初期値を保持する
		var sum = getRGBASummary();
		$("#sign").data("RGBASummary", sum);
	};
	
	signaturePad = new SignaturePad($("#sign").get(0));
	setOptions();
	
	$("#color, #bcolor").on("change", function () {
		setOptions();
	});
	
	$("#weight").on("keyup", function () {
		setOptions();
	});
	
	$("#clearButton").on("click", function(){
		$("#color").val("black");
		$("#bcolor").val("white");
		$("#weight").val("3");
		setOptions();
	});
	
	$("#saveButton").on("click", function(){
		var signaturePad2 = new SignaturePad($("#sign2").get(0));
		var url = signaturePad.toDataURL("image/png");
		signaturePad2.fromDataURL(url);
	});
	
	
	// データチェックボタンクリック
	$("#checkButton").on("click", function(){
		var org = $("#sign").data("RGBASummary");
		var sum = getRGBASummary();
		if (sum != org) {
			alert("何かしら描かれてるよ!");
			window.console && console.log(sum + " / " + org);
		} else {
			alert("何も描かれてないよ!");
			window.console && console.log(sum + " / " + org);
		}
	});
});

起動してみる

初期表示

初期表示画面です。何も描かずに「データチェック」ボタンをクリックします。

 

データチェックボタンクリック

何も描かれていない判定となりました。

描いてからボタンクリック

続いて文字を描いてから「データチェック」ボタンをクリックしたところ、ちゃんと描かれている判定がされました。

まとめ

Canvasを表示した際にCanvas内のRGBA情報を集計・保持しておいて、
データチェックボタンがクリックされた際の集計値と比較する方法で判定をしました。

背景色を設定した場合もしっかりRGBA情報が設定されるため初期状態との比較をしましたが、
そもそも背景色を設定しない場合はデータチェックボタンがクリックされた際に、RGBAの集計値が 0でなければ何かしら描いてある判定ができそうです。

何かのお役に立てれば。

ではでは。

 

スポンサーリンク


関連するコンテンツ

Javascript,開発Javascript

Posted by doradora