不動の鳥の勉強記録

時間があるときに勉強したことをメモします。

nvd3.jsを用いた線グラフ/面グラフの作り方

可視化だという風潮が社内にあるのですが、
周りにコーダーがほとんどいないので、みんなExcelで頑張ってグラフを作っています。
VBAを組んでもいいかと思ったのですが、Excelも最近重いと感じるので、
Webサーバに画面乗っけちゃえば?ということで可視化の取り組みをしたいと思いました。

Javascriptライブラリを探していたところ、下記が有名のようでした。(もっとあるかもしれません)
Javascriptライブラリ
 ・Chart.js:Chart.js | Open source HTML5 Charts for your website
 ・D3.js:D3.js - Data-Driven Documents

D3.jsはhtml5が登場したころから、人気のあるライブラリだった記憶があったため、
今回はD3.jsを利用することに決めました。

ただD3.jsをベースとしたライブラリもたくさんあることがわかり、
どれにしようか悩んでいたところ、
「nvd3.js使いやすいですよー」とアドバイスをくれた方がいたのでnvd3.jsに決めました。

nvd3.jsを用いた線グラフ/面グラフを作った時に躓いた点を忘れないようにメモします。
nvd3.org

■実行環境
 ・Windows 10 Home 64bit
 ・Google Chrome: 64.0.3282.167 (Official Build) (64ビット)
 ・d3.js: 3.5.17
 ・nvd3.js: 1.8.1

■づまづいたポイント1. D3.jsとnvd3.jsのバージョンについて
 nvd3.jsのページを見ると、D3.jsの3.5.17までしか対応しておらず、D3.jsの4.xには対応していないとのことです。
 そのため、D3.jsは最新版ではなくて、3.5.17をダウンロードします。

■つまづいたポイント2. Chromeでサンプルを実行するときのエラーについて
 nvd3.jsのサンプルスクリプトをそのまま実行しようとしたら、
 グラフが表示されないぞ?ということで開発ツールで原因を見ていたところ、
 下記エラーが出てしまいました。おそらくバージョンの問題かと思っていますが…
 細かいところは次に見ようと思います。

Uncaught TypeError: nv.models.lineChart(...).margin(...).useInteractiveGuideline(...).transitionDuration is not a function
    at Object.generate ((index):13)
    at renderLoop (nv.d3.js:94)

とりあえず、問題の行をコメントアウトすれば実行できたので、ひとまずは実行したいことはできました。
細かい設定はドキュメントを見てもらえたらいいかと思います。

サンプルをそのまま持ってきたものは下記になります。

<!DOCTYPE html>
<html>
  <head>
    <title>サンプル</title>
    <link rel='stylesheet' href='/stylesheets/nv.d3.css' />
    <script src="/javascripts/d3.js"></script>
    <script src="/javascripts/nv.d3.js"></script>
    <script>
    nv.addGraph(function() {
      var chart = nv.models.lineChart()
                .margin({left: 100})  //Adjust chart margins to give the x-axis some breathing room.
                .useInteractiveGuideline(true)  //We want nice looking tooltips and a guideline!
//                .transitionDuration(350)  //how fast do you want the lines to transition?
                .showLegend(true)       //Show the legend, allowing users to turn on/off line series.
                .showYAxis(true)        //Show the y-axis
                .showXAxis(true)        //Show the x-axis
                 ;

  chart.xAxis     //Chart x-axis settings
      .axisLabel('Time (ms)')
      .tickFormat(d3.format(',r'));

  chart.yAxis     //Chart y-axis settings
      .axisLabel('Voltage (v)')
      .tickFormat(d3.format('.02f'));

  /* Done setting the chart up? Time to render it!*/
  var myData = sinAndCos();   //You need data...

  d3.select('#chart svg')    //Select the <svg> element you want to render the chart in.   
      .datum(myData)         //Populate the <svg> element with chart data...
      .call(chart);          //Finally, render the chart!

  //Update the chart when window resizes.
  nv.utils.windowResize(function() { chart.update() });
  return chart;
      });

      /* test data generator*/
      function sinAndCos(){
        var sin = [], sin2 = [], cos = [];

        for(var i = 0; i < 100; i++){
          sin.push({x:i, y:Math.sin(i/10)});
          sin2.push({x:i, y:Math.sin(i/10) *0.25 + 0.5});
          cos.push({x:i, y: .5 * Math.cos(i/10)});
        }

        return [
          {
            values: sin, 
            key: 'Sine Wave',
            color:'#ff7f0e',
            area: true
          },
          {
            values: cos,
            key: 'Cosine Wave',
            color: '#2ca02c'
          },
          {
            values: sin2,
            key: 'Another sine wave',
            color: '#7777ff',
            area: true
          }
        ];
      }
    </script>
  </head>
  <body>
    <h1>サンプル</h1>
    <div id="chart">
      <svg></svg>
    </div>
  </body>
</html>

以上。