今年も凄く暑くなってきて、節電も気になり始めたんで、また電力ネタを。
以前、電力使用率を表示するガジェットを作成したけど、Windows8からデスクトップガジェットが使えなくなってしまった。
なので、Windows8上でも簡単に表示できるよう、HTML上で表示できる電力メーターを作ってみた。
丁度、HTML5のスキルアップもしたかったので、Flashのような絵が描ける<canvas>を使って作ることに。
でも、テキストエディタのみで、メーターのイメージを想像しながら作るのは、ちょっと難しかった。。
かなり試行錯誤を繰り返す羽目に。
それでも、なんとかイメージに近いものが出来上がった。

一応グラデーションとか光沢など余計なものも作り込んである。
針と文字は、もうちょい何とかしたかったけど。
特にアプリ化する予定も無く、これで終わりだけど、勿体ないのでOsadaSoft実験室というページを作り、そこに載せて置くことにした。
|
<2022/7/2追記> さすがに9年経って動かなくなってた(Yahoo!電力使用状況APIが閉鎖)。 APIを利用せず、各電力会社のCSVデータから情報取得するよう修正中しました。 関西電力のみ微妙にCSVデータが異なるものの、各社同じCSV形式だったので助かった。 また突然仕様変更等で使えなくなる可能性もありますが、とりあえず復活。 各電力会社のデータ(csv)取得元: |
一応、HTML5で作っているので、最新ブラウザであれば、割とうまく表示できると思う。
まだHTML5自体が仕様Fixしていない(W3CのHTML5勧告は2014年予定)ので、ブラウザによって表示できない部品もある。
例えば、スライダーバーのような<legend>は、Google Crome、Safariなどでは表示できるけど、
Internet Exprolerや、FireFoxでは未対応。
多分、W3Cの仕様Fix前に作り込んでしまうと、後々仕様変更があった場合のユーザー影響があるので、あえて作り込んでいないような。

一応、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を指定しなおして頂戴。






