RubyとJavascriptでグラフを描く【その2】[追記]
【計画最終目標】
□シリアルデータのリアルタイム描画
【計画の中期目標】
□csvデータのJavascriptによるグラフ描画
【直近の課題】
データ処理:Ruby
□シリアル通信機器からのデータ受信・csvへ保存
描画処理:Javascript
■csvデータの読み込み
□異なるデータサイズへの対応
□描画方法の変更
※□は未完、■は完了項目
以上のようになっています。早速csvデータの読み込みと異なるデータサイズへの対応をやっていきます。
そのためにも【その1】でやった【記事1】のJavascriptの内容を再確認していきましょう。
【記事1】
qiita.com
【記事1】のjavascripソースコードを冒頭から4分割にして見ていきます
【ソースコード1】
// 2) CSVから2次元配列に変換 function csv2Array(str) { var csvData = []; var lines = str.split("\n"); for (var i = 0; i < lines.length; ++i) { var cells = lines[i].split(","); csvData.push(cells); } return csvData; }
まずは【ソースコード1】のオリジナル関数のcsv2Arrayを作っている部分です。関数定義内の最初の2行は関数内で使う変数の定義です。csvDataはcsvファイルの中身全体を後で格納し、linesはsplitメソッドによって'\n'を区切りとした配列が格納されるように定義されているのだと思います。for文は他のプログラムでもありますね。詳細は以下のようになっているようです。
for (初期値; 条件式; 増減式) { 繰り返し処理 }
この関数はまずcsvをstrとして読み込みます。次に文字列データをsplitにより'\n'で区切った配列linesとする。その後for文で各行を','区切りの配列にしてpushによりcsvDataにどんどんくっつけていくといった動作をします。そして最後に使った変数を全て出力してもしょうがないので、returnにより処理によって作られたcsvDataのみを出力するようになっています。
【記事2】length: length プロパティ (Array) (JavaScript)
【記事3】push: .push() | JavaScript 日本語リファレンス | js STUDIO
【記事4】split: split メソッド (String) (JavaScript)
【記事5】return: return文の使い方 | JavaScript中級編
【ソースコード2】
function drawBarChart(data) { // 3)chart.jsのdataset用の配列を用意 var tmpLabels = [], tmpData1 = [], tmpData2 = []; for (var row in data) { tmpLabels.push(data[row][0]) tmpData1.push(data[row][1]) tmpData2.push(data[row][2]) };
これはdataの各列を一つの配列として変数に格納しているようです。一箇所rowの表現が何をしているのか分からないので調べてみます。
【記事6】for/in文: for..in文 - 繰り返し処理 - JavaScript入門
記事6より
for("変数" in "オブジェクト"){ }
で配列を順番に読み込んでくれるようです。順番にというのが厄介で、ある列(プロパティ)について順番に読み込んでくれるようです。【記事6】では複数列(複数プロパティ)あるときにはどの列から読み込むのか分からないと書いてあります。
それじゃお手上げだ!
とはならず、あくまでもfor文での行送りを何回繰り返すかという回数をrowに格納できたらOKです。列については、for文の中で列を指定してあげればいいので【ソースコード2】ではdataの行を[row]、列をその後の[]で指定しています。なるほど。
【ソースコード3】
// 4)chart.jsで描画 var ctx = document.getElementById("myChart").getContext("2d"); var myChart = new Chart(ctx, { type: 'bar', data: { labels: tmpLabels, datasets: [ { label: "Tokyo", data: tmpData1, backgroundColor: "red" }, { label: "Osaka", data: tmpData2, backgroundColor: "blue" } ] } }); }
最初のctxはdocumentクラスのgetElementByIdメソッドでmyChartのidを取得しています。取得したidに対してgetContextメソッドで描画機能を有効にする処理を格納しているようです。詳しくは【記事7】に書いてあります。
【記事7】
www.htmq.com
【ソースコード3】が私には見難かったのでちょろっと改行などを弄ってみると…
【ソースコード3】
// 4)chart.jsで描画 var ctx = document.getElementById("myChart").getContext("2d"); var myChart = new Chart( ctx, { type: 'bar', data: { labels: tmpLabels, datasets: [ { label: "Tokyo", data: tmpData1, backgroundColor: "red" }, { label: "Osaka", data: tmpData2, backgroundColor: "blue" } ] } } );
基本的にはChart.jsに描画の有効化とグラフの設定・データを渡してあげている処理になっています。以下のような感じでしょうか。
var myChart = new Chart("描画の有効化", "グラフの設定・データ")
そしてmychartとしてhtmlから呼び出す。それではChartって何なのさ!といいますと、おそらくhtmlファイルのヘッダで
<script src="http://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.min.js"></script>
と読み込んでいるchart.jsであろうと思われます。調べてみると、【記事8】にCDN経由でchart.jsを利用する際には上記を書いておけば利用可能と書いてあることからも、これはローカルにchart.jsファイルをダウンロードしないで利用する方法であることが分かります。…CDNって何でしょうね。こうやってわき道にそれていくのです。CDNは【記事9】で分かりやすく解説されています。なるほどー。
【記事8】
paiza.hatenablog.com
【記事9】
blog.redbox.ne.jp
ということは、これをダウンロードしておけばスタンドアロンのネットに接続されていないPCでも利用可能ということでしょうか。このあたりは後で調べてみます。
さて、話を元に戻すと、グラフの設定・データを確認するところでした。
"グラフの設定・データ" => { type:'bar', datasets:[Data1, Data2] }
と書けばいいようです。datasetsの形式は以下の通りです。
Data1 => {label:"ラベル名", data: データ変数, backgroundColor: "color"}
ここまでくると棒グラフから折れ線グラフに変えるには'bar'=>'line'にすればよさそうです。ためしに変えてみると…
うわぁああ!変な感じになりました。それもそうですよね。chartのオプションでbackgroundColkorだけを指定したままにしているからです。オプションの変更方法は【記事10】を参考にしていろいろといじってみます。
【記事10】
qiita.com
見た目をいろいろといじりたいのですが、今日はもう遅いのでひとまずここまでとしておきます。
[追記:2017.03.14]
中途半端なところで終わっていたので、続きをこの記事に追記しておきます。
ひとまずlineプロットをいい感じで書きます。
type:'line'
にしてその他のプロパティをいじります。
datasets: [ { label: "Tokyo", backgroundColor: "rgba(75,192,192,0.4)", //背景色 borderColor: "rgba(75,192,192,1)", //枠線の色 data: tmpData1 }, { label: "Osaka", backgroundColor: "rgba(75,19,192,0.4)", //背景色 borderColor: "rgba(75,19,192,1)", //枠線の色 data: tmpData2, } ]
と設定すると
以上のようになります。
見た目に関しては、グラフタイプとそのオプションを設定してあげればいろいろとかけそうです。
【ソースコード4】
function main() { // 1) ajaxでCSVファイルをロード var req = new XMLHttpRequest(); var filePath = 'data.csv'; req.open("GET", filePath, true); req.onload = function() { // 2) CSVデータ変換の呼び出し data = csv2Array(req.responseText); // 3) chart.jsデータ準備、4) chart.js描画の呼び出し drawBarChart(data); } req.send(null); } main();
ここではmain関数を定義しています。さて、Ajaxってなんじゃらほいっっと。先ずはwikipedia様。
【記事11】
Ajax - Wikipedia
ふむふむ、続いて解説記事
【記事12】
いまさら聞けないリッチクライアント技術(3):いまさら聞けない、“Ajax”とは何なのか? (1/3) - @IT
googleマップにも使われているのですね!入り口付近の情報は学べました。もう少し調べたいですが、今はここまでにとどめておいて、何をやっているかを理解していきます。
【記事13】
JavaScriptでCSVファイルを読み込む方法 | UX MILK
【記事13】では
var req = new XMLHttpRequest(); // HTTPでファイルを読み込むためのXMLHttpRrequestオブジェクトを生成
と書いてあります。これでオブジェクトを生成すると…なんとなく分かるのですが、ちゃんとした認識を得るために調べます。
【記事14】
オブジェクト指向超入門
【記事15】
oshiete.goo.ne.jp
なるほどー。今はこのくらいにします。さて次は
var filePath = 'data.csv';
これは明らかにcsvファイルのディレクトリ指定ですね。ディレクトリが同じため、今回はファイル名だけでいいのでしょう。
req.open("GET", filePath, true);
これは【記事15】にfilePathにアクセスと書いてあります。
req.onload = function() { }
この部分については【記事16】に書いてあります。
【記事16】
onload - ページ読み込み後に処理を行う方法 | JavaScript プログラミング解説
{ }の中ではcsvファイルをcsv2Arrayで配列"data"に変換し、その後"data"をdrawBarChartに入力して各プロパティ(列のデータに分割してchart.jsのデータセットに入力してグラフ生成という処理になっています。これで晴れて全ての内容を理解しました!
最後に当初の目標の振り返りとちょっと修正です。
【計画最終目標】
□シリアルデータのリアルタイム描画
【計画の中期目標】
□csvデータのJavascriptによるグラフ描画
□メモリに格納したデータのJavascriptによるグラフ描画←追加
【直近の課題】
データ処理:Ruby
□シリアル通信機器からのデータ受信・csvへ保存
□シリアル通信機器からのデータ受信・メモリに格納←追加
描画処理:Javascript
■csvデータの読み込み
■異なるデータサイズへの対応←Done
■描画方法の変更←Done
□csvが更新されたらグラフ更新する←追加
デバイス関係
■シリアルデータ送信機器の準備
□実際の測定機器におけるシリアルデータのフォーマットを再現する←追加
※□は未完、■は完了項目
【後で確認】
hackmylife.net