PHPとJavascriptでリアルタイム(?)3Dグラフ


以下のようなことをすれば、DBのデータをブラウザでリアルタイムに三次元グラフで参照とかできるかもです。

PHPも使えば、概要にあった「当初はPHP-GDプロジェクトとして始まりました…」もなんだか報われる感じです。誰かやればいいのに。
自分でやってみました。

使ったもの

以下のOS/サーバ等を使用しました。バージョンは調べてないけど、昨日インストールした最新のUbuntuに入ったものを使っています。

余談ですが、Ubuntuがすごい。何も設定してないのにすでにちゃんと動いているあたりすごい。

さらに、以下のJavascriptライブラリを使いました。

ライブラリ 用途 入手先
prototype.js 主にAjax http://www.prototypejs.org/
canvas3DGraph.js 三次元グラフの描画 http://dragan.yourtree.org/code/canvas-3d-graph/
excanvas.js IEでのcanvasの使用 http://excanvas.sourceforge.net/

やっていること

DBのテーブルの内容を一定時間毎に自動的に読み取り、三次元グラフを更新しています。
詳しく書くと、以下のような流れになります。

  1. ブラウザのタイマーイベントを1秒間隔で発生させる。
  2. ブラウザのタイマーイベントの処理でAJAXを使ってPHPにリクエストを投げる。
  3. PHPMySQLからデータを取得する。
  4. PHPがデータをJSONへ加工する。
  5. PHPがブラウザにJSONを含めたレスポンスを返す。
  6. ブラウザはレスポンスに含まれるJSONをもとに三次元グラフを描画する。

テーブル構成は以下のようになっており、レコード一行がグラフの棒一本に対応します。

mysql> desc three_dimension;
+-------+-------+------+-----+---------+-------+
| Field | Type  | Null | Key | Default | Extra |
+-------+-------+------+-----+---------+-------+
| x     | float | YES  |     | NULL    |       |
| y     | float | YES  |     | NULL    |       |
| z     | float | YES  |     | NULL    |       |
+-------+-------+------+-----+---------+-------+
3 rows in set (0.00 sec)

動かしてみた

それでは、実際に動かした画面イメージを張り付けていきます。
貼り付けるイメージの画面は位置は以下のようにしています。

Internet Explorer Google Chrome
MySQLのコンソール FireFox

MySQLのコンソールは細かすぎてよく見えないかも・・・。

最初

最初はただ表示するだけなので、前回と代わり映えしません。表示するデータは変えてあります。

データを追加する

左下のMySQLのコンソールでinsert文を実行してデータを追加してみます。

insert into three_dimension values( 200, 300, 400 );

その結果がこちらのイメージです。

三次元グラフの棒が自動的に追加されました!Google ChromeFireFoxはOKです!!
しかし、Internet Explorerだけ更新に失敗してしまいます。調べていませんが、おそらくcanvasタグ周りに原因あるのでしょう。とりあえず今回は無視して続けます。

さらにデータを追加する

もう1件くらい追加してみます。。

insert into three_dimension values( 700, 100, 500 );


大丈夫そうです。

今度はデータを削除してみる

deleteも実行してみます。

delete from three_dimension where x = 500 and y = 500 and z = 500;


ちゃんと削除できています。IEは相変わらずだめですが。

データの更新もしておく

updateもやりました。一律同じ高さにしてしましいます。

update three_dimension set y = 200;


うまくいきました!

ソースコード

このプログラムのソースコードは以下の通りです。

<?
// HTTPレスポンスの文字コードを設定する。
header( "Content-Type: text/html; charset=UTF-8" );

if ( isset( $_GET['ajax'] ) ) {
        // AJAX処理:

        // DBに接続する。
        $mysqli = @new mysqli( 'localhost', 'root', null, 'test' );
        if ( mysqli_connect_errno() ) {
                // 接続に失敗する:
                 die( "接続できませんでした。" . mysqli_connect_error() );
        }

        // DBからデータを取得する。
        if ( ! $result = $mysqli->query( "select * from three_dimension" ) ) {
                // 取得に失敗する:
                 die( "SQLの実行に失敗しました。" . mysqli_connect_error() );
        }

        // データを配列に格納する。
        $data = array();
        while ( $row = $result->fetch_assoc() ) {
                array_push( $data, $row );
        }

        // DBから切断する。
        $result->close();
        $mysqli->close();

        // データをJSONに変換する。
        $json =  json_encode( $data );

        echo $json;

        exit;
}
// 通常処理:

?>


<script type="text/javascript" src="prototype.js"></script>
<script type="text/javascript" src="excanvas.js"></script>
<script type="text/javascript" src="canvas3DGraph.js"></script>
<script type="text/javascript">
/**
 * 3Dグラフを表示する。
 */
function show3DGraph() {
        // データを取得するために、サーバにリクエストを出す。
        var uri = 'http://<? echo $_SERVER['SERVER_NAME'].$_SERVER['SCRIPT_NAME']; ?>';
        var params = 'ajax=true';
        var myAjax = new Ajax.Request(
                uri,
                {
                        method: 'get',
                        parameters: params,
                        onComplete: show3DGraph_cb
                }
        );
}

/**
 * 3Dグラフを表示する。(サーバからのコールバック後の処理)
 */
function show3DGraph_cb( req ) {
        // サーバのレスポンスからデータを取得する。
        var data = eval( req.responseText );

        // graphオブジェクトを取得する。
        var g = new canvasGraph( 'graph' );

        // データを並べ替える。
        data.sort( sortNumByZ );

        // グラフを描く。
        g.drawGraph( data );
}

// 画面ロード時に実行する。
Event.observe( window, "load", function(){
        // 3Dグラフの実行を一定時間毎に行うように、タイマーを設定する。
        setInterval( show3DGraph, 1000 );
});
</script>
<style type="text/css">
#g-holder {
        height:620px;
        position:relative;
}

#canvasDiv{
        border:solid 1px #e1e1e1;
        width:600px;
        height:600px;
        position:absolute;
        top:0px; left:0px;
        z-index:10;
}
#x-label{
        position:absolute;
        z-index:2;
        top:340px;
        left:580px;
}

#y-label{
        position:absolute;
        z-index:2;
        top:10px;
        left:220px;
}

#z-label{
        position:absolute;
        z-index:2;
        top:540px;
        left:10px;
}

#gInfo div.gText{
        position:absolute;
        z-index:-1;
        font:normal 10px Arial;
}
</style>
&nbsp;
<div id="g-holder">
        <div id="canvasDiv">
                <canvas id="graph" width="600" height="600" ></canvas>
                <div id="gInfo"></div>
        </div>
        <div id="controls">
        <!-- (put your controls here, if you need any) -->
        </div>
</div>

さいごに

DBの内容を自動的に取得して3次元グラフを描画する仕組みは実現できました。
以下は課題として残っています。

  • Internet Explorerへの対応
  • DBの内容の自動更新
  • そもそも3次元グラフを何に使う考えること

これらの課題も気が向いたら考えようと思います。