Programming Journal

学習したことの整理用です。

chartkick × Highchartsでドーナツグラフを作る

実装したいこと

  • ドーナツグラフの真ん中に合計額
  • ラベルはグラフ上に表示
  • ラベルが細かくて重なってしまう場合は非表示
  • 凡例を非表示

chartkickを使用したら、簡単に実装できました。
ただ、chartkick × Highchartsについての日本語記事がほぼない&各オプションの指定が公式から探しにくく、苦労しました。

chartkickでは、chart-js Google Charts Highchartsを使用することができます。
最初、chart-jsを使用していたのですが、細かい設定はできない&ラベル表示がデフォルトでないため扱いが難しかったので、途中でHighchartsに変更しました。見た目もHighchartsのほうが綺麗な気がします。

f:id:Study-Diary:20201230183715p:plain
ドーナツグラフ

環境

  • rails (6.0.3.4)

  • "chartkick": "^3.2.1",

  • "highcharts": "^8.2.2",

chartkickのインストール

GitHub - ankane/chartkick: Create beautiful JavaScript charts with one line of Ruby

gem "chartkick"

Rails6なので、

yarn add chartkick highcharts
require("chartkick").use(require("highcharts"))

View

line_chart(表示したいデータ) pie_chart(表示したいデータ)のように、表示させたいviewファイルに記述するだけでグラフを生成できます。
今回は円グラフを作りたいので、pie_chartを選択します。 (テンプレートエンジンはslimを使用)

#公式の例
= pie_chart Goal.group(:name).count 

グローバルオプションの追加

今回は1種類のグラフしか使用しないので、全体に適用するグローバルオプションを指定していきます。
Chartkickで使用できるオプションと、Highchartsから使うオプションで記述方法が異なります。
Highchartsのオプションは、library以下に記述していきます。

Chartkick.options = {
  donut: true, # ドーナツグラフ
  width: '400px',
  colors: [ "#769fcd",
            "#b9d7ea",
            "#d6e6f2",
            "#f7fbfc",
          ],
  message: {empty: "データがありません"},
  thousands: ",", 
  suffix: "円",
  legend: false, # 凡例非表示
  library: { # ここからHighchartsのオプション
    title: { # タイトル表示(ここでは、グラフの真ん中に配置して,viewでデータを渡しています。*後述)
      align: 'center',
      verticalAlign: 'middle',
    },
    chart: {
      backgroundColor: 'none',
      plotBorderWidth: 0, 
      plotShadow: false
    },
    plotOptions: {
      pie: {
        dataLabels: {
          enabled: true, 
          distance: -40, # ラベルの位置調節
          allowOverlap: false, # ラベルが重なったとき、非表示にする
          style: { #ラベルフォントの設定
            color: '#555', 
            textAlign: 'center', 
            textOutline: 0, #デフォルトではラベルが白枠で囲まれていてダサいので消す
          }
        },
        size: '110%',
        innerSize: '60%', # ドーナツグラフの中の円の大きさ
        borderWidth: 0,
      }
    },
  }
}

Highchartsの公式でDemoが見られるので、これをcodepenで操作しながらオプションを試しました。 annotations.labelOptions.shadow | Highcharts JS API Reference

View

これは力技で無理やり実装したので、多分もっといい方法がありそう
コントローラーで定義したインスタンス変数@expenses @sum_of_expenditureを取得して表示しています。(内容は省略)

= pie_chart @expenses,library: {title: {text: "支出<br> #{@sum_of_expenditure)"}}

グラフ内に表示したいタイトルはグローバルオプションではなく、ローカルオプションで渡します。