WebSocketとGoroutineによるリアルタイムのグラフ表示 – (1)クライアントサイド

2017.05.22

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

ブラウザをリロードすることなくリアルタイムで更新されるグラフをお手軽?に作成できたらいいなと思い、WebSocketとGolangのGoroutineを組み合わせたサンプルを作成してみました。

特定のハッシュタグが含まれるツイートをストリームで取得し、指定したキーワードの出現回数をグラフに表示するサンプルです。ハッシュタグ、キーワードともアプリの起動引数で指定できるようにしました。

クライアントサイドのグラフ表示にはGoogle Chartsを使用し、先に書いたようにWebSocketにてサーバと遣り取りしました。

作成したサンプルの動き

起動してブラウザでlocalhost:8080にアクセスすると、以下のようなグラフと、「socket open」の下にツイートが表示されます。スクリーンショットだけでは分かりにくいかもしれませんが、このグラフとツイートがリアルタイムで更新されます。

websocket-google-charts-realtime-graph-1-1

クライアントサイドの実装

では実装についてです。まずはクライアントサイドから書いていきたいと思います。ソースは以下のようになります。

templates/index.tpl
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript">
 
    // load library
    google.load('visualization', '1', {'packages':['corechart']});

    // WebSocket
    $(function () {
        var socket;
        if (window.WebSocket === undefined) {
            $("#container").append("Your browser does not support WebSockets");
            return;
        } else {
            socket = initSocket();
        }
        function initSocket() {
            var socket = new WebSocket("ws://localhost:8080/ws");
            var container = $("#containerDiv");
            socket.onopen = function() {
                container.append("<p>Socket is open</p>");
            };
            socket.onmessage = function (e) {
                var json = JSON.parse(e.data);
                var keyCounts = json.keyCounts;
                var tweet = json.tweet;

                // create data table
                var dt = new google.visualization.DataTable();
                dt.addColumn('string', 'keyword');
                dt.addColumn('number', 'count');
                Object.keys(keyCounts).forEach(function(key) {
                    var value = this[key];
                    dt.addRow([key, value]);
                }, keyCounts);

                // display options
                var options = {
                    title: 'tweet keyword count',
                };
                
                // create bar chart
                var chart = new google.visualization.BarChart(document.getElementById('chartDiv'));

                // draw chat
                chart.draw(dt, options);

                // display tweet
                container.append("<p>" + tweet + "</p>");
            }
            socket.onclose = function () {
                container.append("<p>Socket closed</p>");
            }
            return socket;
        }
    });
</script>
</head>
<body>
  
  <!--  chart display area -->
  <div id="chartDiv" style="width: 100%; height: 350px"></div>
  <!--  websocket message area -->
  <div id="containerDiv"></div>
  
</body>
</html>

ファイルの拡張子は「.tpl」となっていますが、次回に書くgolangのサーバサイドでこのファイルをテンプレートとして使用するためです。おそらく.htmlにしても動くと思います。

見てのようにWebSocketとGoogle Chartsのソースが混ざった形となっています。詳細はコメントに記述しておりますが、大まかに書くと

  • divタグでグラフ、ツイートなどのを表示するエリアを指定(64〜67行目)
  • Google Chartsのライブラリの読み込み(9行目)
  • WebSocketでサーバ側から受信したらグラフに表示(26〜52行目)

を行なっています。

まとめ

WebSocketとGoogle Chartsを組み合わせることで、サクッとリアルタイムに更新されるグラフを作成することができました。次回はgolangによるサーバサイドの実装について書きたいと思います。

参考サイト

以下のサイトを参考にさせて頂きました。ありがとうございました。
[Google Charts]棒グラフを作成する
simple websocket example with golang
Google Visualization API Reference