こんにちは、くまごろーです。
今作成中の家計簿アプリで、収入・支出の内訳を円グラフにしたいと考えています。
それで、今回は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 参考