2016年3月21日月曜日

epochを使って簡単にリアルタイムチャートを作る手順

リアルタイムチャートを作りたくて、ブログとか少し調べてました。
【Javascript】グラフ・チャート描画用のjsライブラリまとめ  に色々書いてあって比較しやすかったです。
簡単に使えて、キレイで無料で、商用にも使えるライセンス等のごくごく入門的な観点で選んでいたのですが、Epochというのが良さそうだったので今回はEpochを使います。

Epoch本家サイト を見ると次のように書いてあります。
A general purpose real-time charting library for building beautiful, smooth, and high performance visualizations.
「リアルタイムチャート作りたいなら黙ってEpoch使っとけ。」とのこと。はい、分かりました。

手順1. デモを動かす

Epochのリアルタイムチャートのドキュメントページ見ただけだと情弱の私には分からなかった。
それなので、デモを動かします。

次の様なリアルタイムチャートを描画したいと思います。


まず必須のライブラリを読み込みます。

  • <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
  • <script src="//d3js.org/d3.v3.min.js"></script>
  • <script src="/javascripts/epoch.min.js"></script>

次に、データ取得部分がわからなかったので、ドキュメントページのHTMLを見るとたったこれだけの記述。

========================
<div id="real-time-line" class="epoch" style="height: 200px"></div>

<script>
$(function() {
    var data = new RealTimeData(2);

    var chart = $('#real-time-line').epoch({
        type: 'time.line',
        data: data.history(),
        axes: ['left', 'bottom', 'right']
    });

    setInterval(function() { chart.push(data.next()); }, 1000);
    chart.push(data.next());
});
</script>
========================

newしてるRealTimeDataってなんじゃい!と思ったら、html丈夫のdata.jsに書いてありました。このjsも持ってきて読み込みます。

はい、これで動きました。jsの読み込みとか間違って無ければ、短いhtml書くだけで大丈夫なはず。


手順2. 描画に必要な処理をザックリ理解する

デモを動かすところまでに出てきたメソッドの意味などを一応確認します。
  • 必須ライブラリ(jquery, d3, epoch)の読み込み
  • 描画に必要なデータフォーマット(ドキュメント参考)を作る処理の実装 ※デモではdata.jsの部分
  • divにidふって描画領域の確保
  • $().epochメソッドで初期化
  • pushメソッドでデータ追加
  • setIntervalで定期処理実施
このくらいですね。

手順3. nodejs+websocketに応用する

前回の記事「Xivelyみたいに投げられた値をリアルタイム描画してみたい」を目指していたので、投げられた値をそのまま描画したかったのです。websocketならnodejsの評判が良さそうなのでnodejsをテストしてました。

D3.jsベースのEpochを使ってリアルタイムチャートを描いてみる」のページがまさにそれで、詳しく書いてあります。


以下、私がやったメモ。

・nodejsの実行環境用意

・expressのジェネレータ使ってパッケージ作成

・socket.io使う準備
ここ、このやり方で正しいのか分からんけど、www/binでserverオブジェクト作ってて、socket.ioのオブジェクト欲しくて、ただ、別のファイルでsocket.ioのオブジェクト使いたかったのでグローバルにした。グローバル変数あんまり使いたくないんだけど、本当はどうやるのがいいんだろ。誰か教えて。。
======
/**
 * Create HTTP server.
 */

var server = http.createServer(app);

/**
 * websocketを使うために接続
 */
global.socketio = require("socket.io").listen(server);
======

・app.jsにfeedsっていうエンドポイント追加。
======
var feeds = require('./routes/feeds');
======

・そんで、feeds.jsってファイル作って、websocketで接続できるようにした。
=====
var express = require('express');
var router = express.Router();

/* GET feeds listing. */
router.get('/', function(req, res, next) {
  res.send('thanks!');

  value = req.query.value | 0;
  global.socketio.emit("paramData", {message: 'hello', value: value});
});

module.exports = router;
=====

サーバサイドここまで。

クライアントサイドのは、デモで作ったリアルタイムチャートのコードをベースにする。
変更部分は、ランダムでデータ出力していた部分をサーバから受け取った値を表示するようにすること。
currentValueというグローバル変数を用意して、この値を変更、描画するように改造する。

・websocketの部分はこんな感じ。
======
var socketio = io.connect(window.location.href);
socketio.on("paramData", function(d) {
  $('#messages').append(d.value);
  // グラフデータ受信
  currentValue = d.value;
});
======

・グラフ描画部分はこんな感じ。
======
$(function() {
    var data = new RealTimeData(2);

    var chart = $('#lineChart').epoch({
        type: 'time.line',
        data: data.history(),
        axes: ['left', 'bottom', 'right']
    });

    setInterval(function() { chart.push(data.next(currentValue)); }, 1000);
    chart.push(data.next(currentValue));
});
======

・あとは、data.nextで受け取った値を描画するようにすればOK!


epoch君、これからよろしく。