[Chart.js] 積み上げ折れ線グラフの実装

2018年12月28日

chart.js テクノロジー プログラミング

このところハマり気味のChart.jsですが、今回はクライアントからの要望で、積み上げ折れ線グラフの設置を行います。 積み上げ棒グラフが一般的なんですが、個人的趣向が強い依頼があり、積み上げ折れ線グラフというスタイルの構築案件になりました。 そもそも積み上げグラフってどういうモノなのかわからない人の為に説明をしておきますね。

積み上げグラフについて

一般的なグラフは、「折れ線グラフ」と「棒グラフ」が主流ですが、

折れ線グラフ

棒グラフ

どちらも同じデータを使って表現することができますが、これは一軸データに対しての表現はシンプルにできますが、エクセル表のような多段レコード形式のデータの表現は、複雑な表現が必要になります。 例えば、下記の様なテーブルデータがある場合はどうでしょう? 株式会社ミクシィの株主数の年度遷移データですが、株の購入者分類と年次のマトリクスデータですが、一軸のグラフでは表現できない事がわかります。 総数の割合を表したい場合のグラフは、パイチャートが有効なのですが、これは年次というそれの遷移を表現する必要があるので、そうした場合に有効なのが、積み上げグラフになります。 棒グラフで表すと総数に対する割合が視覚的にみてわかるのでわかりやすいグラフになります。 これを積み上げ折れ線グラフにすると・・・ このようになります。 分布の割合と遷移具合が分かってこれはこれで悪くないかもしれませんね。 ちなみに、このグラフは「個人その他」の値を非表示にして表示しています。 ※圧倒的割合で、他の値が潰れてしまうので、わかりやすいグラフにしています。 折れ線グラフでは、積み上げグラフ要素で扱うと、線が交差して非常に醜い見た目になってしまうので、「積み上げ」にするメリットは大きいという事が感じました。

Chart.jsでの対応

chartjsでの基本は、3点あり、datasetsのそれぞれのfillの値を直前の値を参照する様にする事と、 stack=1にセットする事、 options設定に、「stacked=true」を入れる事で"bar"でも"line"でも積み上げグラフが表現できます。 実際のコードは以下の様になります。 { "type": "line", "data": { "labels": [ "2013", "2014", "2015", "2016", "2017" ], "datasets": [ { "label": "政府及び地方公共団体", "data": [ 0, 0, 0, 0, 0 ], "backgroundColor": [ "rgba(100 , 190 , 196 , 0.5)", "rgba(100 , 190 , 196 , 0.5)", "rgba(100 , 190 , 196 , 0.5)", "rgba(100 , 190 , 196 , 0.5)", "rgba(100 , 190 , 196 , 0.5)" ], "pointBackgroundColor": [ "rgba(100 , 190 , 196 , 0.5)", "rgba(100 , 190 , 196 , 0.5)", "rgba(100 , 190 , 196 , 0.5)", "rgba(100 , 190 , 196 , 0.5)", "rgba(100 , 190 , 196 , 0.5)" ], "pointBorderColor": "rgba(120 , 120 , 120 , 0.8)", "borderColor": "rgba(120 , 120 , 120 , 0.8)", "borderWidth": 1, "lineTension": 0, "stack": 1, "fill": "origin" }, { "label": "金融機関", "data": [ 7, 15, 20, 17, 19 ], "backgroundColor": [ "rgba(172 , 155 , 209 , 0.5)", "rgba(172 , 155 , 209 , 0.5)", "rgba(172 , 155 , 209 , 0.5)", "rgba(172 , 155 , 209 , 0.5)", "rgba(172 , 155 , 209 , 0.5)" ], "pointBackgroundColor": [ "rgba(172 , 155 , 209 , 0.5)", "rgba(172 , 155 , 209 , 0.5)", "rgba(172 , 155 , 209 , 0.5)", "rgba(172 , 155 , 209 , 0.5)", "rgba(172 , 155 , 209 , 0.5)" ], "pointBorderColor": "rgba(120 , 120 , 120 , 0.8)", "borderColor": "rgba(120 , 120 , 120 , 0.8)", "borderWidth": 1, "lineTension": 0, "stack": 1, "fill": "-1" }, { "label": "金融商品取引業者", "data": [ 29, 58, 61, 22, 37 ], "backgroundColor": [ "rgba(125 , 171 , 202 , 0.5)", "rgba(125 , 171 , 202 , 0.5)", "rgba(125 , 171 , 202 , 0.5)", "rgba(125 , 171 , 202 , 0.5)", "rgba(125 , 171 , 202 , 0.5)" ], "pointBackgroundColor": [ "rgba(125 , 171 , 202 , 0.5)", "rgba(125 , 171 , 202 , 0.5)", "rgba(125 , 171 , 202 , 0.5)", "rgba(125 , 171 , 202 , 0.5)", "rgba(125 , 171 , 202 , 0.5)" ], "pointBorderColor": "rgba(120 , 120 , 120 , 0.8)", "borderColor": "rgba(120 , 120 , 120 , 0.8)", "borderWidth": 1, "lineTension": 0, "stack": 1, "fill": "-1" }, { "label": "その他の法人", "data": [ 241, 239, 196, 122, 100 ], "backgroundColor": [ "rgba(184 , 48 , 179 , 0.5)", "rgba(184 , 48 , 179 , 0.5)", "rgba(184 , 48 , 179 , 0.5)", "rgba(184 , 48 , 179 , 0.5)", "rgba(184 , 48 , 179 , 0.5)" ], "pointBackgroundColor": [ "rgba(184 , 48 , 179 , 0.5)", "rgba(184 , 48 , 179 , 0.5)", "rgba(184 , 48 , 179 , 0.5)", "rgba(184 , 48 , 179 , 0.5)", "rgba(184 , 48 , 179 , 0.5)" ], "pointBorderColor": "rgba(120 , 120 , 120 , 0.8)", "borderColor": "rgba(120 , 120 , 120 , 0.8)", "borderWidth": 1, "lineTension": 0, "stack": 1, "fill": "-1" }, { "label": "外国法人等-個人以外", "data": [ 66, 309, 399, 469, 518 ], "backgroundColor": [ "rgba(222 , 133 , 176 , 0.5)", "rgba(222 , 133 , 176 , 0.5)", "rgba(222 , 133 , 176 , 0.5)", "rgba(222 , 133 , 176 , 0.5)", "rgba(222 , 133 , 176 , 0.5)" ], "pointBackgroundColor": [ "rgba(222 , 133 , 176 , 0.5)", "rgba(222 , 133 , 176 , 0.5)", "rgba(222 , 133 , 176 , 0.5)", "rgba(222 , 133 , 176 , 0.5)", "rgba(222 , 133 , 176 , 0.5)" ], "pointBorderColor": "rgba(120 , 120 , 120 , 0.8)", "borderColor": "rgba(120 , 120 , 120 , 0.8)", "borderWidth": 1, "lineTension": 0, "stack": 1, "fill": "-1" }, { "label": "外国法人等-個人", "data": [ 34, 70, 56, 32, 38 ], "backgroundColor": [ "rgba(255 , 220 , 80 , 0.5)", "rgba(255 , 220 , 80 , 0.5)", "rgba(255 , 220 , 80 , 0.5)", "rgba(255 , 220 , 80 , 0.5)", "rgba(255 , 220 , 80 , 0.5)" ], "pointBackgroundColor": [ "rgba(255 , 220 , 80 , 0.5)", "rgba(255 , 220 , 80 , 0.5)", "rgba(255 , 220 , 80 , 0.5)", "rgba(255 , 220 , 80 , 0.5)", "rgba(255 , 220 , 80 , 0.5)" ], "pointBorderColor": "rgba(120 , 120 , 120 , 0.8)", "borderColor": "rgba(120 , 120 , 120 , 0.8)", "borderWidth": 1, "lineTension": 0, "stack": 1, "fill": "-1" }, { "label": "個人その他", "data": [ 15297, 33831, 31351, 16771, 11187 ], "backgroundColor": [ "rgba(128 , 192 , 256 , 0.8)", "rgba(128 , 192 , 256 , 0.8)", "rgba(128 , 192 , 256 , 0.8)", "rgba(128 , 192 , 256 , 0.8)", "rgba(128 , 192 , 256 , 0.8)" ], "pointBackgroundColor": [ "rgba(128 , 192 , 256 , 0.8)", "rgba(128 , 192 , 256 , 0.8)", "rgba(128 , 192 , 256 , 0.8)", "rgba(128 , 192 , 256 , 0.8)", "rgba(128 , 192 , 256 , 0.8)" ], "pointBorderColor": "rgba(120 , 120 , 120 , 0.8)", "borderColor": "rgba(120 , 120 , 120 , 0.8)", "borderWidth": 1, "lineTension": 0, "stack": 1, "fill": "-1" } ] }, "options": { "tooltips": { "callbacks": {} }, "scales": { "yAxes": [ { "ticks": { "beginAtZero": true }, "stacked": true } ] }, "plugins": { "filler": { "propagate": true } } } } ポイント個所は以下の3つです。
1. datasets/data[]/stack = 1 2. datasets/data[]/fill = "-1" ※一番最初の値のみ"origin"にする事と、-1は数値ではなく文字列で登録しなければならない。 3. options/plugins/filler/propagate = true
さほどの労力ではないのですが、検索で詳細にたどり着きにくかったので、メモがてらブログに書いておきました。

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。