Flotを使ったリアルタイムグラフ更新を少しカスタマイズしてみた

Javascript製のグラフ描画用ライブラリとして、色々あるうち、Flotを使ってみた。

他にもいくつか選択肢はあったんだけど、

  • Ajaxで外部データを取り込んでグラフ描画が可能
  • 以前も使ったことのある実績(簡単に使える)
  • jQuery製であること
  • ひと通りのAPIが提供されていて、サンプルやリファレンスなどのドキュメントが充実している
  • MITライセンス

といった理由により、他の選択肢と比べて一歩抜き出ているので、Flotにしてみた。

今回はリアルタイム更新の機能を試してみたかったので、サンプル( http://people.iola.dk/olau/flot/examples/realtime.html )に少し手を加えてみた。

改良点は、

  • X軸を時系列にする。
  • データは外部JSONデータを取り込む。
  • グラフを複数本(2本)にする。
  • 初期表示時はデータ数は0個で、更新のたびに1個増えていき、最大50個まで。データ数が50の場合、一番古いデータから捨てていく。

といった点(どれも他のサンプルの組み合わせ)。

取得するJSONデータは以下のようなものとする。

{"foo": 3.14, "bar": 1.41}

で、作ったJavascriptは以下のとおり。元々のサンプルを少し修正してできた。

$(function () {
    // we use an inline data source in the example, usually data would
    // be fetched from a server
    var data1 = [], data2 = [], totalPoints = 50;
    function loadData() {
        $.getJSON(
            "hoge.json",
            function(json){
                if (data1.length > totalPoints) {
                    data1 = data1.slice(1);
                }
                if (data2.length > totalPoints) {
                    data2 = data2.slice(1);
                }
                var t = (new Date()).getTime();
                data1.push([t, json.foo]);
                data2.push([t, json.bar]);
            }
        );
    }

    // setup control widget
    var updateInterval = 200;
    $("#updateInterval").val(updateInterval).change(function () {
        var v = $(this).val();
        if (v && !isNaN(+v)) {
            updateInterval = +v;
            if (updateInterval < 1)
                updateInterval = 1;
            if (updateInterval > 2000)
                updateInterval = 2000;
            $(this).val("" + updateInterval);
        }
    });

    // setup plot
    var options = {
        series: { shadowSize: 0 }, // drawing is faster without shadows
        yaxis: { min: 0 },
        xaxis: { ticks: 5, show: true, mode: "time", timeformat: "%H:%M:%S" }
    };
    var plot = $.plot($("#placeholder"), [data1, data2], options);

    function update() {
        loadData();
        plot.setData([data1, data2]);
        plot.setupGrid();
        plot.draw();
        
        setTimeout(update, updateInterval);
    }

    update();
});