もふもふ技術部

IT技術系mofmofメディア

Vue+c3.jsでグラフ描画してみる

実際の案件でインタラクティブな折れ線グラフ描画機能を実装する必要があったため、いくつかライブラリを調べていました。 描画するグラフでは下記のような機能を実装する方針だったので、拡張性の高いライブラリを探していたところ、c3.jsというライブラリに行き着きました。

  • カレンダーで選択した期間のデータを表示する
  • 選択した期間を変更すれば、グラフもインタラクティブに変更される
  • 1つのx軸上に2種類以上のデータを表示する
  • グラフで表示したいデータを変更すれば、グラフもインタラクティブに変更される
  • y軸を左右2軸にする
  • 選択した期間に応じて、複数の背景色をつけたい
  • 実線、点線など2種類以上のグラフ線を使いたい
  • tooltipの中にmodal表示用ボタンを入れたい

Javascriptのグラフ描画用ライブラリと言えばChart.jsが有名ですが、tooltipのカスタマイズがしづらいという問題があったので、カスタマイズの効くc3.jsを採用することになりました。

Vueアプリケーションの作成

まずはvue-cliをインストールし、プロジェクトを作成します。

yarn global add @vue/cli
vue create chart-app

c3の設定

まずはライブラリをインストールします。Vueでc3を使う場合、vue-c3も必要になるのでこちらも合わせてインストールします。

yarn add c3 vue-c3

次にvue-c3のREADMEを参考にして、折れ線グラフ用のVueコンポーネントを用意します。

// src/components/LineChartC3.vue

<template>
  <vue-c3
    :handler="handler"
  />
</template>

<script>
import Vue from 'vue'
import VueC3 from 'vue-c3'
import 'c3/c3.min.css'

export default {
  components: {
    VueC3,
  },

  data: () => ({
    handler: new Vue(),
    options: {
      data: {},
    }
  }),

  mounted () {
    this.handler.$emit('init', this.options)
  },
}
</script>

1つずつ説明します。 まず、メインコンポーネント<vue-c3/>です。これに、handlerという名前のpropsを渡します。 handlerはVueインスタンスを初期化したものを用意し、それに対して$emit('init', this.options)という形でemitすることで、c3のAPIを実行します。

そしてimport 'c3/c3.min.css'でc3のスタイルをインポートするのを忘れずに。これをしないとスタイルが崩れてしまいます。

データの設定

今回はカレンダーで選択した期間のデータ(日別売上、利益など)をグラフ表示するという要件です。まずは、データを表示出来るようにしていきます。 今回扱うデータはAPIで返却されたものをそのまま使いたいので、columns型で設定することにします。

日付ラベルの設定

最初にx軸の日付ラベルの設定を行います。

// src/components/LineChartC3.vue

...

<script>
...

export default {
...

  data: () => ({
    handler: new Vue(),
    options: {
      data: {
        x: 'date',
        columns: [
          ['date','2020-10-01','2020-10-02','2020-10-03','2020-10-04','2020-10-05'],
        ],
      },
      axis: {
        x: {
          type: 'timeseries',
          tick: {
            format: '%Y-%m-%d'
          }
        },
      },
    }
  }),

...

}
</script>
  • options.data.x: x軸指定。columnsのデータ名を指定する
  • options.data.columns: グラフに表示させるデータ配列。先頭要素をデータラベルにする
  • options.axis.x: x軸の設定を行う

以上の設定をしてもグラフは何も表示されません。実際にグラフ表示するにはデータを入れてあげる必要があります。

// src/components/LineChartC3.vue

...

data: {
  x: 'date',
  columns: [
    ['date','2020-10-01','2020-10-02','2020-10-03','2020-10-04','2020-10-05'],
    ['売上額', 10000, 30000, 20000, 40000, 50000],
    ['利益率', 30, 20, 25, 10, 50],
  ],
},
...

グラフが描画されましたね!

vue-c3-1

しかし、現状は売上額と利益率が同じ軸で表示されてしまっていて、売上額に比べ利益率のスケールが小さ過ぎるためほぼ直線になっています。
そこで、左軸を売上額、右軸を利益率の2軸にしていきます。

// src/components/LineChartC3.vue

...

data: {
  x: 'date',
  columns: [
    ...
  ],
  axes: {
    '売上額': 'y',
    '利益率': 'y2',
  },
  axis: {
    x: {
      type: 'timeseries',
      tick: {
        format: '%Y-%m-%d'
      }
    },
    y: {
      label: {
        text: '売上額',
        position: 'outer-middle',
      }
    },
    y2: {
      show: true,
      label: {
        text: '利益率',
        position: 'outer-middle',
      }
    }
  },
},
...
  • options.data.axes: データがどちらの軸なのかを指定
  • options.axis.x: x軸の設定を行う
  • options.axis.y: y軸の設定を行う

vue-c3-2

2軸でのデータ表示が出来ましたね!

まとめ

いかがでしたか?
c3.jsは他にもたくさんのオプションがあるので、実装時にかなり融通が効くと思います。
tooltipのカスタマイズはかなりのボリュームになるので、今回はこの辺りにしようと思います。