D3.js + NVD3 + Sinatra + Heroku で作るインタラクティブなデータ可視化デモ

# インタラクションの実装

さて[昨日](http://qiita.com/ynakayama/items/7af2034add81859e6ca5)は [D3.js 日本語訳](http://ja.d3js.info/alignedleft/tutorials/d3/)の全 16 章の内容を駆け足で一気に書き下ろしてみましたが、この内容だけですと静的なプロッティングしかできずなんとも消化不良です。

そこで今回は[前々回](http://qiita.com/ynakayama/items/3432755caac199438e1b)にも紹介した [NVD3](http://nvd3.org/) との組み合わせでいよいよ D3.js の肝心の目玉であるインタラクションを実装していきます。

完成形のデモアプリケーションは[こちら](http://d3js-stacked-chart.herokuapp.com/)から閲覧できます。
(うまく表示されない場合はブラウザをリロードしてみてください)

## Heroku を利用する

いままでは画像をペタペタと記事に貼ってきましたがインタラクションを見せるには Qiita に画像を貼るだけでは不十分です。そこでデモアプリケーションとして外部のサイトにデプロイすることを考えます。こんなときに非常に便利なのが [Heroku](https://devcenter.heroku.com/) というサイトです。詳細は[この辺り](http://blog.ruedap.com/2011/04/29/ruby-heroku-web-app-development-tips-1)を読めば分かると思いますが要は無料でも使える [PaaS](http://ja.wikipedia.org/wiki/PaaS) サービスです。

Heroku に静的な HTML だけを置くことは通常はできません。そこで D3.js を [Sinatra](http://www.sinatrarb.com/) アプリケーションのビューとして組み込むことによって Heroku へのデプロイを可能にします。

今後 D3.js を使うにあたり Ruby などのアプリケーションの一部として開発を進めるようなことがあっても、このように最初から連携しておくと何かと応用が効いて便利ですね。

## ビューの実装

index.erb という名前でビューを作成します。とはいっても ERB の部分は何もありませんので中身は単なる HTML ファイルです。今回はこれをデモアプリで表示するのが目的です。一応 ERB という扱いなので views サブディレクトリに配置します。

```html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>D3.js</title>
    <!-- D3.js 本体を読み込む (予め公式サイトからダウンロードしておく) -->
    <script type="text/javascript" src="/d3/d3.min.js"></script>
    <!-- NVD3.js を読み込む (予め公式サイトからダウンロードしておく) -->
    <script type="text/javascript" src="/nvd3/nv.d3.min.js"></script>
    <!-- NVD3.js 用の CSS を忘れないように -->
    <link rel="stylesheet" type="text/css" href="/nvd3/nv.d3.css" />
    <!-- 自作の CSS を読み込む -->
    <link rel="stylesheet" type="text/css" href="style.css" />
  </head>

  <body class='with-3d-shadow with-transitions'>
    D3.js
    <div>
      <!-- チャートを表示するための空の SVG -->
      <svg id="chart1"></svg>
    </div>
    <!-- 自作の JS を読み込む -->
    <script type="text/javascript" src="d3js.my.js"></script>
  </body>
</html>
```

## データの定義

JSON で次のようにデータを定義します。

```json
[
  {
    "key" : "キー項目名" ,
    "values" : [ [ "UNIX 時刻印 (数値)" , "データの値 (数値)"]]
  } ,
  {
    "key" : "キー項目名" ,
    "values" : [ [ "UNIX 時刻印 (数値)" , "データの値 (数値)"]]
  }
]
```

なお元となるデータの整形については以前に書いた [Python での整形テクニックを利用する](http://qiita.com/ynakayama/items/824269b484e721f3ec82)と良いでしょう。

## NVD3 を利用したプロッティング

d3.json メソッドで読み込んだ JSON 形式のデータを NVD3 で描画します。なお一応 Sinatra アプリケーションなので JavaScript や CSS 、データとなる JSON のように外に提供するリソースは public サブディレクトリに配置します。 D3.js や NVD3.js も[以前に解説した](http://qiita.com/ynakayama/items/362049808223c191d252)通り筆者は外部サイトから読み込む方法を採用したくないので同様に public に配置します。

```js
d3.json('data.json', function(data) {
  // 色の定義
  var colors = d3.scale.category20();
  keyColor = function(d, i) {return colors(d.key)};

  // グラフの描画
  // NVD3 を使って Stacked Area Chart な関数を定義する
  var chart;
  nv.addGraph(function() {
    chart = nv.models.stackedAreaChart()
                  .useInteractiveGuideline(true)
                  .x(function(d) { return d[0] })
                  .y(function(d) { return d[1] })
                  .color(keyColor)
                  .transitionDuration(300);

    // X 軸
    chart.xAxis
        .tickFormat(function(d) { return d3.time.format('%x')(new Date(d)) });

    // Y 軸
    chart.yAxis
        .tickFormat(d3.format(',.2f'));

    // D3.js で SVG を選択してデータの配列回数分だけメソッドを実行
    d3.select('#chart1')
      .datum(data)
      .transition().duration(1000)
      .call(chart) // NVD3 の関数を .call する
      .each('start', function() {
          setTimeout(function() {
              d3.selectAll('#chart1 *').each(function() {
                console.log('start',this.__transition__, this)
                if(this.__transition__)
                  this.__transition__.duration = 1;
              })
            }, 0)
        })
    nv.utils.windowResize(chart.update);
    return chart;
  });
});
```

## CSS の実装

CSS も public サブディレクトリに置きます。

```css
body {
  overflow-y:scroll;
}

text {
  font: 12px sans-serif;
}

#chart1, #chart2 {
  height: 500px;
}
```

## デモアプリケーションの完成

あとは Heroku に git push すれば完成です。

D3.js デモアプリケーション
http://d3js-stacked-chart.herokuapp.com/

Chrome ブラウザで閲覧するのが推奨です。

## まとめ

今回は NVD3 のデモ通りのアプリケーションを実装し Heroku にデプロイしてみました。これでようやく手持ちのデータを整形すればインタラクティブなデータ可視化をできそうな手応えが感じられるようになったのではないでしょうか。