JavaScriptチャートライブラリを選ぶにあたって考えたこと

こんにちは、トレンド調査ラボの井上寛之(@inohiro)です。 クックパッドの検索ログを基にした法人向けデータサービス「たべみる」の開発を担当しています。

本稿では、現在開発を行っているスマートフォン向けウェブアプリケーション(Rails)で採用した、 JavaScriptチャートライブラリを選定するにあたって検討した観点について述べます。 また、実際に採用したライブラリと、その利用例を簡単に紹介します。

ウェブ上に無数にあるJavaScriptチャートライブラリから、最適なものを一つ選択するのは なかなか難しい作業ではないかと考えています。おそらく、これから記述する条件を満たすライブラリは数多く存在し、 今回私が選択したライブラリ以上に良いものがあるのではないかと思います。 「何を以って良いライブラリとするか」という議論もまた難しい話題です。 そのようなライブラリについては、はてブコメントでそっと教えていただけると幸いです。

描くチャートの種類

現在開発中のアプリケーションでは、以下の二種類のチャートを描く画面がありました。

  • ラインチャート
  • スパークラインチャート

ラインチャートは、いわゆる折れ線グラフです。

スパークラインチャート(スパークラインとも)は、ラインチャートの一種です。ただし、X軸やY軸が省略されており、 詳細な値はわかりません。時系列的な傾向を、ぱっと見て簡単に把握できることを目的としたチャートです。

スパークラインチャートは、以下のようにExcelなどの表計算アプリケーションで簡単に作成することができます。

linechart

ラインチャートを描くライブラリ

ラインチャートを描くライブラリを選定する際に検討した条件について述べます。

今回描くラインチャートでは、ビジネス上の要求として「Y軸(および値)を表示しない」という条件がありました。 具体的な数字は示さずに、その項目の時系列的な変化を視覚的に示すためにチャートを利用したいということです。

他の条件としては、チャートライブラリに限った話ではありませんが、ドキュメントやウェブ上の閲覧できる事例は多いほうが良いでしょう。 継続的にメンテナンスされていることも大切です。ソースコードが公開されていれば、おかしな挙動に対してPRを送ることもできそうです。

また、スマートフォン向けウェブアプリケーションであるため、レスポンシブであると嬉しいです。 さらにはRuby Gemとして公開されていると、Railsアプリケーションから使う場合に便利です。 これは、vendor/assets 以下にファイルを直接 コピーするのと比較して、ライブラリの最新バージョンに追従しやすくなりますし、 アプリケーション本体のソースコードもコンパクトに保てる利点があります。

少々話が脱線してしまいましたが、選定における条件をまとめると、以下のようになります。

  • ラインだけ表示したい
    • Y軸を非表示にするオプションがある
    • ツールチップを非表示にするオプションがある
  • 扱うのが簡単
  • オープンソース
  • ドキュメントが十分にある
  • 継続的にメンテナンスされている
  • 商用サイトに利用しても問題のないライセンス
  • レスポンシブ
  • Ruby Gemとして公開されている(導入・管理が簡単)

この条件で、今回選んだライブラリは「Chart.js」です。 ドキュメントはシンプルですが詳細であり、 とりあえずのものを作ってみるのも簡単でした。 レスポンシブオプションを有効にすることで、画面の横幅が変わった時に動的にグラフや背景の方眼が再描画され、 画面幅が異なるスマートフォンから使うウェブアプリケーションに便利です。

また、Ruby Gemsとして公開されている(chart-js-rails)ので、 Gemfileに一行追加するだけで、すぐに利用可能です。

イマイチな点としては、ラベルを等間隔に配置するようなオプションが無いことです。

Chart.jsによるラインチャートの描画例

以下に描画の例を示します。

linechart

  • Gemfile
gem 'chart-js-rails'
  • 画面
<canvas class="chart" />
  • データセットとグラフの作成(coffee script)
    • ラベル(X軸)を等間隔に表示したかったので、偶数番目を空文字列にしています(2行目)
#= require Chart

dataSet = {
  labels: _(labels).map((label, index) => if index % 2 == 0 then '' else label),
  datasets: [
    {
      strokeColor : "#dcdcdc",
      pointColor : "#dcdcdc",
      pointStrokeColor : "#ffffff",
      data: values[1]
    },
    {
      strokeColor : "#ff9933",
      pointColor :  "#ff9933",
      pointStrokeColor : "#ffffff",
      data : values[0]
    }
  ]
}

new Chart($("#chart").get(0).getContext("2d")).Line(dataSet, {
  # -- global options --
  animation: false
  responsive: true
  scaleShowLabels: false
  showTooltips: false
  # -- line chart options --
  bezierCurve: false
  datasetFill: false
})

他の候補

  • Google Chart Tools
    • Chart.js の方がレスポンシブ対応の面で上回ったので、今回は不採用
    • chartkikという使いやすそうなGemがあります
    • google_visualrを利用すると、render _chart メソッドを使って、JSを書かずにグラフが描けます
  • NVD3
    • d3.js はカスタマイズ性が高く難しいそうですが、NVD3を使うと比較的簡単に描けるようです
    • (この記事を書くことになってから知ったので、選定時は漏れていました)
  • morris.js
    • 簡単に使えそうです。社内ツールでも使われています
    • (こちらも後日になって教えてもらったため、選定時は漏れていました)

スパークラインチャートを描くライブラリ

スパークラインチャートを描くライブラリを選定するにあたって検討した内容は、実はあまりなく、 商用サイトで利用しても問題ないかという点だけでした。

今回の場合は既にjQueryを使っていたので、jQueryのプラグインとして使える「Peity」を利用しました。スパークライン以外にも、かわいいパイチャート、バーチャートを描くことができます。

似たライブラリとして、「jQuery Sparklines」があります。 GitHubリポジトリを見たところ、masterへの最新のコミットが2013年9月であり、またPull Requestがかなり放置されてしまっている状態から、メンテナンスされていないと判断しました。

PeityもRuby Gem(jquery-peity-rails)として公開されています。

イマイチな点としては、HTMLタグの中に直接データを書く必要があることです。data属性に書いておいて、いい感じに指定できるとなお良い気がします。

Peity によるスパークラインチャートの描画例

以下に描画の例を示します。

img

  • Gemfile
gem 'jquery-rails'       # 必要に応じて
gem 'jquery-peity-rails'
  • 画面
<span class="sparkline">0.13,0.17,0.22,0.30,0.41,0.85</span>
  • ラインチャートを作る
#= require 'jquery'
#= require 'jquery.peity'

option = {
  fill: "#ffd592"
  height: 16
  max: null
  min: 0
  stroke: "#ff9900"
  strokeWidth: 2
  width: 75
}
$('span.sparkline').peity('line', option)

他の候補

まとめ

本稿ではスマートフォン向けウェブアプリケーションで利用する、 JavaScfiptチャートライブラリの選定において検討した観点について述べました。 細かい条件や要求は個々のプロジェクトによって異なりますが、選定上の観点は使いまわせると思います。

まとめると、今回は以下の観点で検討しました。

  • 適切なライセンス
  • 継続的にメンテナンスされている
  • オープンソースである
  • ドキュメントが十分にある
  • 扱うのが簡単(<=> カスタマイズ性が高い)
  • レスポンシブか
  • 他のライブラリとの兼ね合い
    • jQuery と使うのか、Angular.js と使うのか、等
  • Gem として使うことができる(導入が簡単か)
    • とくにRailsアプリケーションの場合
    • イマドキは webpack 等を使うのが良さそう

今回は検討しませんでしたが、他の観点としては、

  • サポートするチャートの種類
  • サポートするブラウザ、バージョン
  • 描画方式
    • DOM要素に対してイベントをバインドしたい場合は、SVGを選択する等
  • Bower や npm から使えるか

などが考えられます。

また、Wikipediaの英語版には「Comparison of JavaScript charting frameworks 」 というページがあり、チャートの種類ごとにサポート状況が一覧できます。ただし、比較的名が知られたものしかリストされていないかもしれません。

無数にあるJavaScriptチャートライブラリの全てを見て回り、条件のあうものの中から最適な一つを見つけるというのは、 あまり現実的ではありません。 読者の皆さんが次にチャートライブラリを選定する際に、本稿をご活用いただければ幸いです。

/* */ @import "/css/theme/report/report.css"; /* */ /* */ body{ background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527163350.png'); background-repeat: repeat-x; background-color:transparent; background-attachment: scroll; background-position: left top;} /* */ body{ border-top: 3px solid orange; color: #3c3c3c; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; line-height: 1.8; font-size: 16px; } a { text-decoration: underline; color: #693e1c; } a:hover { color: #80400e; text-decoration: underline; } .entry-title a{ color: rgb(176, 108, 28); cursor: auto; display: inline; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; font-size: 30px; font-weight: bold; height: auto; line-height: 40.5px; text-decoration: underline solid rgb(176, 108, 28); width: auto; line-height: 1.35; } .date a { color: #9b8b6c; font-size: 14px; text-decoration: none; font-weight: normal; } .urllist-title-link { font-size: 14px; } /* Recent Entries */ .recent-entries a{ color: #693e1c; } .recent-entries a:visited { color: #4d2200; text-decoration: none; } .hatena-module-recent-entries li { padding-bottom: 8px; border-bottom-width: 0px; } /*Widget*/ .hatena-module-body li { list-style-type: circle; } .hatena-module-body a{ text-decoration: none; } .hatena-module-body a:hover{ text-decoration: underline; } /* Widget name */ .hatena-module-title, .hatena-module-title a{ color: #b06c1c; margin-top: 20px; margin-bottom: 7px; } /* work frame*/ #container { width: 970px; text-align: center; margin: 0 auto; background: transparent; padding: 0 30px; } #wrapper { float: left; overflow: hidden; width: 660px; } #box2 { width: 240px; float: right; font-size: 14px; word-wrap: break-word; } /*#blog-title-inner{*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-position: left 0px;*/ /*}*/ /*.header-image-only #blog-title-inner {*/ /*background-repeat: no-repeat;*/ /*position: relative;*/ /*height: 200px;*/ /*display: none;*/ /*}*/ /*#blog-title {*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527172848.png');*/ /*background-repeat: no-repeat;*/ /*background-position: left 0px;*/ /*}*/