今年も凄く暑くなってきて、節電も気になり始めたんで、また電力ネタを。
以前、電力使用率を表示するガジェットを作成したけど、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を指定しなおして頂戴。