HTML5で各電力会社の電力使用率をアナログメーターで描画するサンプルを作ってみた。

HTML5で各電力会社の電力使用率をアナログメーターで描画するサンプルを作ってみた。

今年も凄く暑くなってきて、節電も気になり始めたんで、また電力ネタを。
以前、電力使用率を表示するガジェットを作成したけど、Windows8からデスクトップガジェットが使えなくなってしまった
なので、Windows8上でも簡単に表示できるよう、HTML上で表示できる電力メーターを作ってみた。
丁度、HTML5のスキルアップもしたかったので、Flashのような絵が描ける<canvas>を使って作ることに。
でも、テキストエディタのみで、メーターのイメージを想像しながら作るのは、ちょっと難しかった。。
かなり試行錯誤を繰り返す羽目に。
それでも、なんとかイメージに近いものが出来上がった。
meter
一応グラデーションとか光沢など余計なものも作り込んである。
針と文字は、もうちょい何とかしたかったけど。
特にアプリ化する予定も無く、これで終わりだけど、勿体ないのでOsadaSoft実験室というページを作り、そこに載せて置くことにした。

HTML5+Ajaxによる電力メーター

<2022/7/2追記>
さすがに9年経って動かなくなってた(Yahoo!電力使用状況APIが閉鎖)。
APIを利用せず、各電力会社のCSVデータから情報取得するよう修正中しました。
関西電力のみ微妙にCSVデータが異なるものの、各社同じCSV形式だったので助かった。
また突然仕様変更等で使えなくなる可能性もありますが、とりあえず復活。

各電力会社のデータ(csv)取得元:

北海道電力 https://denkiyoho.hepco.co.jp/area_forecast.html
東北電力 https://setsuden.nw.tohoku-epco.co.jp/graph.html
北陸電力 https://www.rikuden.co.jp/nw/denki-yoho/
東京電力 https://www.tepco.co.jp/forecast/
中部電力 https://powergrid.chuden.co.jp/denkiyoho/
関西電力 https://www.kansai-td.co.jp/denkiyoho/
中国電力 https://www.energia.co.jp/nw/jukyuu/
四国電力 https://www.yonden.co.jp/nw/denkiyoho/
九州電力 https://www.kyuden.co.jp/td_power_usages/pc.html
沖縄電力 https://www.okiden.co.jp/denki2/


一応、HTML5で作っているので、最新ブラウザであれば、割とうまく表示できると思う。
まだHTML5自体が仕様Fixしていない(W3CのHTML5勧告は2014年予定)ので、ブラウザによって表示できない部品もある。
例えば、スライダーバーのような<legend>は、Google Crome、Safariなどでは表示できるけど、
Internet Exprolerや、FireFoxでは未対応。
多分、W3Cの仕様Fix前に作り込んでしまうと、後々仕様変更があった場合のユーザー影響があるので、あえて作り込んでいないような。
iphone
一応、iPhone(Safari)でも表示できた。
HTMLソース:

<!doctype html>
<html>
<head>
	<meta charset="utf-8">
	<title>OsadaSoft実験室・HTML5+Ajaxによる電力メーター</title>
	<script>
	// グローバル変数宣言
	var denUsageRate;		// 電力使用率(初期値は最大値の100)
	var wkDenryoku;			// 描画中の電力会社
	var wkUsageRate;		// 描画中の針の値
	var needleTimer=null;	// 針描画用タイマー
	var den={hokkaido:"北海道電力",tohoku:"東北電力",tokyo:"東京電力",chubu:"中部電力",kansai:"関西電力",kyushu:"九州電力"};
	// 電力使用状況APIのレスポンス結果を処理するコールバック関数

	function powerUsageCallback(json) {
		if(needleTimer!=null) return;
		var usageVal = json.ElectricPowerUsage.Usage.$;
		var CapVal = json.ElectricPowerUsage.Capacity.$;
		denUsageRate = toInt((usageVal/CapVal)*100);
		document.getElementById("resArea").innerHTML =
		"<table border=1>" +
		"<tr><td>Area</td><td>" + json.ElectricPowerUsage.Area + "</td></tr>" +
		"<tr><td>Usage</td><td>" + addFigure(json.ElectricPowerUsage.Usage.$) + " KW</td></tr>" +
		"<tr><td>Capacity</td><td>" + addFigure(json.ElectricPowerUsage.Capacity.$) + " KW</td></tr>" +
		"<tr><td>Date (houre)</td><td>" + json.ElectricPowerUsage.Date + " (" + json.ElectricPowerUsage.Hour + ")</td></tr></table>";
		// 0から取得した値まで10msごとに針描画更新
		needleTimer = setInterval(drawMeter, 10);
	}

	// メーター表示処理
	function showMeter() {
		if(needleTimer!=null) return;
		denUsageRate = 100;
		wkUsageRate = -1;
		var radDen = document.getElementsByName("rDen");
		for(i=0;i<radDen.length;i++){
			if (radDen[i].checked) {
				wkDenryoku = radDen[i].value;
			}
		}

		var aplId = "";		※ここに自分用のYahoo!デベロッパーネットワークのアプリケーションIDを指定
		var url = "http://setsuden.yahooapis.jp/v1/Setsuden/latestPowerUsage?";
		var params = "appid=" + aplId + "&area=" + wkDenryoku + "&output=json&callback=powerUsageCallback";
		var script = document.createElement("script");
		script.type = "text/javascript";
		script.src = url + params;
		document.body.appendChild(script);
	}

	// 整数化
	function toInt(val){
		return ~~(val);
	}

	// カンマ区切りの数値に変換
	function addFigure(str) {
		var num = new String(str).replace(/,/g, "");
		while(num != (num = num.replace(/^(-?\d+)(\d{3})/, "$1,$2")));
		return num;
	}

	// Canvas描画処理
	function drawMeter(){
		var canvas	= document.getElementById("myCanvas");
		var cv		= canvas.getContext("2d");
		var scale = document.dForm.meterSize.value *10
		var center	= {x : scale / 2, y : scale / 2};
		var hLen	= scale * 0.8 / 2;		// 針の長さ
		var fSize	= scale / 9;			// フォントサイズ

		// メーター背景の円描画
		cvSize = document.getElementById("myCanvas").getAttribute("width");
		cv.clearRect(0, 0, cvSize, cvSize);
		cv.beginPath();
		cv.arc(center.x , center.y , scale/2 , 0 , Math.PI * 2 , false);

		// グラデーション指定
		var grad = cv.createRadialGradient(center.x , center.y , 0 ,center.x , center.y ,scale/2);
		grad.addColorStop(0.00, "#505050");
		grad.addColorStop(0.40, "#303030");
		grad.addColorStop(0.90, "#101010");
		grad.addColorStop(0.95, "#404040");
		grad.addColorStop(1.00, "#000000");
		cv.fillStyle = grad;
		cv.fill();
		// Canvasの色、フォント
		cv.fillStyle	= "#FFFFFF";
		cv.font			= "bold " + fSize + "px 'MS Pゴシック'";
		// 文字盤表示
		for(var i=0;i<=10;i++){
			var radian = ((270 / 10) * i +180) * Math.PI / 180;
			var xx = center.x + hLen * Math.sin(radian) - fSize/4;
			var yy = center.y - hLen * Math.cos(radian) + fSize/4;
			cv.fillText(i, xx, yy);
		}

		// 針を指定値まで増加させていく
		if(wkUsageRate==-1){
			wkUsageRate=0;
		}else{
			addVal = toInt((denUsageRate - wkUsageRate) / 20);
			if(addVal<1) addVal = 1;
			wkUsageRate += addVal;
		}
		if(wkUsageRate>=denUsageRate){
			clearInterval(needleTimer);
			needleTimer=null;
		}

		// 値表示
		cv.fillStyle	= "#B0B0B0";
		cv.font = fSize * 0.7 + "px 'MS Pゴシック'";
		cv.fillText(den[wkDenryoku], center.x + scale/20, center.y + scale/8);
		cv.fillText(wkUsageRate + " % ", center.x + scale/10, center.y + scale/4);

		// 針(影)描画
		var hRadian = ((270 * wkUsageRate / 100) + 180) * Math.PI / 180;
		var pos_x = cPoint(center, hLen, hRadian);
		cv.strokeStyle = "#550000";
		cv.lineWidth = scale / 40;
		cv.beginPath();
		cv.moveTo(center.x, center.y);
		cv.lineTo(pos_x.x, pos_x.y);
		cv.moveTo(0,0);
		cv.stroke();

		// 針(中心)描画
		cv.strokeStyle = "#FF5555";
		cv.lineWidth = scale / 100;
		cv.beginPath();
		cv.moveTo(center.x, center.y);
		cv.lineTo(pos_x.x, pos_x.y);
		cv.moveTo(0,0);
		cv.stroke();
		cv.fillStyle = 'rgb(50, 50, 50)';
		cv.arc(center.x , center.y , scale/20 , 0 , Math.PI * 2 , false);
		cv.fill();

		// 光沢を付ける(半透明の円描画)
		cv.fillStyle = 'rgba(224, 224, 224, 0.1)';
		cv.arc(center.x , center.y/20 , scale/1.5 , 0 , Math.PI * 2 , false);
		cv.fill();
	}

	// 針先端の座標取得
	var cPoint = function(center, hookLength, radian) {
		return {
			x : center.x + hookLength * Math.sin(radian),
			y : center.y - hookLength * Math.cos(radian)
		};
	}
	</script>
</head>
<body onload="showMeter()">
	<h3>HTML5+Ajaxによる電力メーター</h3>
	<a href="http://developer.yahoo.co.jp/webapi/shinsai/setsuden/v1/latestpowerusage.html" target="_blank">Yahoo!電力使用状況API</a>
	から各電力会社の電力使用量を取得し、電力使用率をHTML5の<Canvas>にアナログ風メーターとして描画するサンプルです。<br>
	<br>
	<hr>
	<div style="width:100%;">
		<form name="dForm">
			<fieldset style="display:inline;">
				<legend>電力会社</legend>
				<input type=radio name="rDen" onClick="showMeter()" value="hokkaido" >北海道電力
				<input type=radio name="rDen" onClick="showMeter()" value="tohoku">東北電力
				<input type=radio name="rDen" onClick="showMeter()" value="tokyo" checked>東京電力
				<input type=radio name="rDen" onClick="showMeter()" value="chubu">中部電力
				<input type=radio name="rDen" onClick="showMeter()" value="kansai">関西電力
				<input type=radio name="rDen" onClick="showMeter()" value="kyushu">九州電力
			</fieldset>
			<fieldset style="display:inline;">
				<legend>メーター描画サイズ</legend>
				小<input type="range" name="meterSize" min="10" max="40" value="20" onchange="showMeter()">大
			</fieldset>
		</form>
		<br><br>
		<table>
			<tr><td>
			<canvas id="myCanvas" width="400" height="400" style="background-color:#E0E0E0;"></canvas>
			</td><td>
			電力使用状況API レスポンス結果<br><br>
			<div id="resArea">Yahoo! API Result Area</div>
			</td></tr>
		</table>
		<br><br>
	</div>
	<hr>
	<br>
	※HTML5対応ブラウザで表示してください。<br>
</body>
</html>

※aplIdには、自分のYahoo!デベロッパーネットワークのアプリケーションIDを指定しなおして頂戴。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


*