コンテンツへスキップ

hifiveでリアルタイムグラフを描こう

by : 2014/11/06

hifiveはMVCフレームワークであり、使用するUI部品に関しては基本的に制約がありません。要件に応じてマッチするものを選択できるようになっています。とはいえ、業務アプリケーションでよく使われる機能・パターンはやはり存在します。また、よく使われる部品だけに、機能性はもちろん互換性やパフォーマンスに関して高いレベルが求められることもしばしばです。そこで、hifiveではよく使われるUIコンポーネントを順次開発中です。

そこで、今回はその開発中ライブラリの中からチャートライブラリをご紹介します。ここでは機能をそぎ落としたシンプルな見た目で紹介します。

必要なライブラリ

グラフを描く際には標準のhifiveライブラリの他に、

が必要です。また描画に際して、

があると良いです。これらを含めたHTMLは次のようになります。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">
    <link href="//code.htmlhifive.com/h5.css" rel="stylesheet">
    <link href="//hifive.github.io/hifive-ui-library/hifive-ui-library/WebContent/components/chart/src/chart.css" rel="stylesheet">
    <title>hifive example</title>
  </head>
  <body>
    <div id="container">
      <div id="chart" ></div>
    </div>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="//code.htmlhifive.com/ejs-h5mod.js"></script>
    <script src="//code.htmlhifive.com/h5.js"></script>
    <script src="//hifive.github.io/hifive-ui-library/hifive-ui-library/WebContent/components/chart/src/graphic-renderer.js"></script>
    <script src="//hifive.github.io/hifive-ui-library/hifive-ui-library/WebContent/components/chart/src/chart.js"></script>
    <script src="javascripts/chartController.js"></script>
  </body>
</html>

chartController.jsは実際にグラフを描画する内容を記述します。

chartController.js

全体像としては以下のようになります。

(function() {
  /**
  データ生成関数
  */

  var DUMMY_DATA_SIZE, createChartDummyData, pageController;
  DUMMY_DATA_SIZE = 300;
  createChartDummyData = function(median, vibration, size) {
    var i, ret;
    ret = [];
    i = 0;
    if (typeof size === 'undefined') {
      size = DUMMY_DATA_SIZE;
    }
    while (i < size) {
      ret.push({
        y: median + (Math.random() - 0.5) * vibration * 2
      });
      i++;
    }
    return ret;
  };
  pageController = {
    __name: "ui.chart.pageController",
    _series: [],
    _dataIndex: 0,
    _width: 600,
    _height: 480,
    _chartController: h5.ui.components.chart.ChartController,
    __meta: {
      _chartController: {
        rootElement: "#chart"
      }
    },
    __ready: function(context) {
      var _this;
      this._series.push(this._createNewSeries());
      this._chartController.draw({
        chartSetting: {
          width: this._width,
          height: this._height
        },
        axes: {
          xaxis: {
            off: true
          },
          yaxis: {
            lineNum: 10,
            fontSize: "7pt",
            autoScale: function(min, max) {
              return {
                rangeMax: 550,
                rangeMin: 250
              };
            },
            range: {
              min: 0,
              max: 500
            }
          }
        },
        seriesDefault: {
          dispDataSize: 100,
          mouseover: {
            tooltip: false
          }
        },
        series: this._series
      });
      _this = this;
      setInterval(function() {
        return _this.go(createChartDummyData(400, 100, 1));
      }, 1000);
    },
    go: function(data) {
      var addData, movedNum;
      movedNum = this._chartController.go(1);
      if (movedNum === 1) {
        return true;
      }
      addData = [
        {
          name: this._series[0].name,
          data: data[0]
        }
      ];
      this._chartController.addData(addData);
      return this._dataIndex++;
    },
    _createNewSeries: function() {
      var data, i, len, name, newData;
      data = createChartDummyData(400, 100);
      newData = [];
      i = 0;
      len = parseInt(this._dataIndex / DUMMY_DATA_SIZE) + 1;
      while (i < len) {
        newData = newData.concat(data);
        i++;
      }
      newData = newData.concat(data.slice(0, this._dataIndex % data.length));
      name = "series_" + this._series.length;
      return {
        name: name,
        type: "line",
        data: newData,
        color: "#1E98B9",
        animateNum: 20
      };
    }
  };
  h5.core.expose(pageController);
})();

$(function() {
  h5.core.controller("body", ui.chart.pageController);
});

描画される結果は次の通りです。

処理内容について

では順番に処理を見ていきます。まずはコントローラになったタイミングで呼ばれる __ready についてです。

まず最初にデータを作成しています。今回はダミーデータを生成しています。

this._series.push(this._createNewSeries());

次はチャートコントローラに対してオプションを渡しています。

チャートの大きさはコントローラのプロパティに設定した値を使っています。

this._chartController.draw({
  chartSetting: {
    width: this._width,
    height: this._height
  },

グラフX/Y軸に関する設定です。今回はY軸について補助線を引いています。

axes: {
    xaxis: {
      off: true
    },
    yaxis: {
      lineNum: 10,
      fontSize: "7pt",
      autoScale: function(min, max) {
        return {
          rangeMax: 550,
          rangeMin: 250
        };
      },
      range: {
        min: 0,
        max: 500
      }
   }
}

描画するデータについて表示数、マウスオーバー時の指定を行っています。今回はツールチップなしです。

seriesDefault: {
    dispDataSize: 100,
    mouseover: {
      tooltip: false
    }
  },
  series: this._series
});

基本的にはここまででグラフ描画に関する指定は終わりです。

さらに今回はリアルタイムグラフとして、1000ミリ秒ごとにデータを追加しています。

_this = this;
  setInterval(function() {
    return _this.go(createChartDummyData(400, 100, 1));
  }, 1000);
},

データの作成について

データの作成は上記の _createNewSeries にて行っています。

var data, i, len, name, newData;
data = createChartDummyData(400, 100);
newData = [];
i = 0;
len = parseInt(this._dataIndex / DUMMY_DATA_SIZE) + 1;
while (i < len) {
  newData = newData.concat(data);
  i++;
}
newData = newData.concat(data.slice(0, this._dataIndex % data.length));
name = "series_" + this._series.length;
return {
  name: name,
  type: "line",
  data: newData,
  color: "#1E98B9",
  animateNum: 20
};

今回は1つのデータしかありませんので色は固定としています。

上半分で行っているのは、データの表示数がオーバーフローしないための処理になります。基本的にはnameにシリーズ名、dataにプロットするデータを与えているだけです。

1000ミリ秒ごとの更新

グラフの描画更新処理は以下のようになっています。

var addData, movedNum;
movedNum = this._chartController.go(1);
if (movedNum === 1) {
  return true;
}
addData = [
  {
    name: this._series[0].name,
    data: data[0]
  }
];
this._chartController.addData(addData);
return this._dataIndex++;

与えられたダミーデータの一つをchartControllerに追加しています。その前に_chartController.go(1)を使ってデータを1つ左へ移動させています。これを繰り返すことでリアルタイムにグラフが更新されていく仕組みが実現します。

実際に動かした結果が次のチャートです。


この基本的な動きさえ押さえておけばシリーズを追加したり、色や描画方法を変えるのはさほど難しくありません。業務システム内でリアルタイム描画のグラフが求められた際にはぜひ使ってみてください。

なお、もっとリッチなチャート機能を試してみたい場合は、こちらのチャートデモをお試しください。シリーズの追加や積み上げグラフ、開始/停止などが試せるようになっています。

hifive – HTML5企業Webシステムのための開発プラットフォーム

HTML5企業Webシステムのための開発プラットフォーム

From → hifive, HTML5

コメントは受け付けていません。

%d人のブロガーが「いいね」をつけました。