MENU

【Chart.js】DBから検索したデータをグラフで表示する。【SpringBoot】

こんにちは、くまごろーです。
今作成中の家計簿アプリで、収入・支出の内訳を円グラフにしたいと考えています。
それで、今回はChart.jsというグラフ描画ライブラリに挑戦してみることにしました。
 
www.chartjs.org
 
で、生じた疑問が、「DBから引き出した結果をChart.jsで表示させるにはどうしたらいいんだろう?」というもの。
その解決方法についてまとめます。


1 コード例を見てみると・・・
 
不勉強でJavaScriptのこと全然わかってませんが、サイトに掲載されているコード例を見てみます。

var myDoughnutChart = new Chart(ctx, {
    type: 'doughnut',
    data: data,
    options: options
});

data = {
    datasets: [{
        data: [10, 20, 30]
    }],

    labels: [
        'Red',
        'Yellow',
        'Blue'
    ]
};

 
上記コードを見ると、カテゴリと値が配列の形で格納されていることがわかります。
ということで、グラフに表示させたいデータを配列型でThymeleafに渡せばうまくいきそう。
 
 
 
2 コントローラークラス
 
コントローラーからリポジトリクラスを呼び出し、グラフに描画させたい数値を検索します。

@GetMapping("/main")
  public String main(@ModelAttribute MoneyRecord moneyRecord, Authentication loginUser, Model model) {
    //カテゴリ一覧(label)を配列に代入する
    //DBのレコードをListクラスで取得
    List<String> expenseCategory = new ArrayList<String>();
    for(int i = 1; i < CategoryCodeToName.Categories.size(); i++) {
      expenseCategory.add(CategoryCodeToName.Categories.get(i));
    }
    //Listを配列に変換
    String expenseLabel[] = expenseCategory.toArray(new String[expenseCategory.size()]);
		

    //カテゴリ毎の合計(data)を設定
    //DBのレコードをListクラスで取得
    List<SummaryByCategory> expenseByCategory = moneyRecordRepository.findCategorySummaries(loginUser.getName(), "2020-12");
    List<BigDecimal> expenseAmmount = new ArrayList<BigDecimal>();
    for(int i = 0; i < expenseByCategory.size()-1; i++) {
      expenseAmmount.add(expenseByCategory.get(i).getSum());
    }
    //配列に変換
    BigDecimal expenseData[] = expenseAmmount.toArray(new BigDecimal[expenseAmmount.size()]);
				
    model.addAttribute("expenseLabel", expenseLabel);
    model.addAttribute("expenseData", expenseData);
		
    return "main";
}




3 viewファイル(Thymeleaf)

コントローラークラスで配列にした値(data)とカテゴリ(label)を代入します。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
  <script th:src="@{/webjars/jquery/3.5.1/jquery.min.js}"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.bundle.js"></script>
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>title</title>
</head>
<body>
	<div class="container">
	<div class="row">
	<div class="col m6 s12">
	<div class="exChart">
  <canvas id="expenseChart" style="display: block; height: 320px; width: 640px;" width="800" height="400" class="chartjs-render-monitor"></canvas>
  </div>
  </div>
  </div>
</div>
  <!-- CDN -->
<script type="text/javascript" th:inline="javascript">

  var ctx = document.getElementById("expenseChart");
  var expenseChart = new Chart(ctx, {
    type: 'doughnut',
    data: {
      labels: [[ ${expenseLabel} ]], //変数式で取り出す
      datasets:[{
          backgroundColor: [
            "rgb(255, 99, 132)",
            "rgb(54, 162, 235)",
            "rgb(255, 205, 86)",
            "rgb(255, 99, 71)",
            "rgb(173, 255, 47)",
            "rgb(100, 149, 237)",
            "rgb(221, 160, 221)",
            "rgb(244, 164, 96)",
            "rgb(240, 248, 255)",
            "rgb(192, 192, 192)",
            "rgb(220, 20, 60)",
            "rgb(189, 183, 107)",
            "rgb(46, 139, 87)",
            "rgb(72, 209, 204)",
            "rgb(218, 112, 214)",
            "rgb(210, 105, 30)",
            "rgb(47, 79, 79)"
          ],
          data:[[${expenseData}]],  //labelと同様
      }]
    },
    options: {
      title: {
        display: true,
        text: '支出'
      }
    }
  }); 
</script>	
</body>
</html>

 
 
 
4 結果
 
上記のコードで実行した結果、こんな感じになりました。

まだまだ改善したいところはあるけど、基本のやり方はクリアできたかな(・_・)
 
 
 
5 参考