複合チャートが描きたい
棒グラフと折れ線グラフを1つのチャート内に表示したりするアレが描きたかった。英語ではMixed Chartって言うんですかね。Google Chartではわりと以前からできていたようですが、Chart.jsでは、Ver.2.0(2016/04リリース)からの新機能だそうです。
このコンテンツでは、このグラフを作ります。
chart.js の基礎
この章は chart.js を使ったことがある人は読み飛ばしてください。
chart.jsとは
WEB上にグラフを描くための、Javascriptライブラリです。
詳しくはググってください。実はあまり知りません。げふげふ……。
Ver.2 ってどうやって使うの?
いきなりコケたんですが、上記公式サイトのGet Started!で始めると、Node.jsで使うことが前提になっていて、ふつうにWebブラウザ上への組み込み方が出てこなかったんですよね。見かたが悪かったのかもしれませんが……。
(2017年9月現在 CDNは下記サイトにわかりやすくリンクされています!)
組み込み用のコードはCDNに公開されているので、無理にダウンロードせず、それをそのまま使うのがカンタンです。
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.bundle.min.js"></script>
bundle とそうでないのと2種類ありますが、bundle は、Moment.js というライブラリがバンドルされているそうです。他のところで Moment.js を組み込んでいるとよろしくないようですが、なんじゃそれ?と思う場合は bundle 版を使っておくのが無難と思います。
まずはふつうに描いてみる
chart.js を使うには、まず canvas を用意して…
<div class="container" style="width:100%">
<canvas id="canvas"></canvas>
</div>
スクリプトで描く。これがキホン。
※たとえ後々 line チャートしか使わなくなったとしても、ここでは bar を指定する必要があります。おそらく「外枠」を含めた指定で、line でロードされる外枠は複合チャートに対応していない、ということと思われます。
※Ver.2.7.1では bar だと bar しか表示されないという指摘がありましたが、当方では再現されませんでした。何か条件があるのか調査中……。(2018年2月)
<script>
window.onload = function() {
ctx = document.getElementById("canvas").getContext("2d");
window.myBar = new Chart(ctx, {
type: 'bar', // ここは bar にする必要があります
data: barChartData,
options: complexChartOption
});
};
</script>
あえて順番を前後させましたが、データセットと…
<script>
// とある4週間分のデータログ
var barChartData = {
labels: ['8/26','8/27','8/28','8/29','8/30','8/31','9/1',
'9/2','9/3','9/4','9/5','9/6','9/7','9/8',
'9/9','9/10','9/11','9/12','9/13','9/14',
'9/15','9/16','9/17','9/18','9/19','9/20','9/21','9/22'
],
datasets: [
{
label: 'sample-line',
data: ['0.155','0.118','0.121','0.068','0.083','0.060','0.067',
'0.121','0.121','0.150','0.118','0.097','0.078','0.127',
'0.155','0.140','0.101','0.140','0.041','0.093','0.189',
'0.146','0.134','0.127','0.116','0.111','0.125','0.116'
],
borderColor : "rgba(254,97,132,0.8)",
backgroundColor : "rgba(254,97,132,0.5)",
},
{
label: 'sample-bar',
data: ['0.3','0.1','0.1','0.3','0.4','0.2','0.0',
'0.2','0.3','0.11','0.5','0.2','0.5','0.4',
'0.0','0.3','0.7','0.3','0.6','0.4','0.9',
'0.7','0.4','0.8','0.7','0.4','0.7','0.8'
],
borderColor : "rgba(54,164,235,0.8)",
backgroundColor : "rgba(54,164,235,0.5)",
},
],
};
</script>
チャート全体のオプションも用意します。チャートオプションは、今はまずこれだけ。
<script>
var complexChartOption = {
responsive: true,
};
</script>
以上を1つのファイルにまとめると、こんなグラフができあがります。
複合チャートにする
データセットオプションに type
そのまま複合チャートにするのはとってもカンタンで、データセットの各データに、type:
というオプションを付けるだけです。「データセット」のオプションです。お間違えなきよう。
<script>
// とある4週間分のデータログ
var barChartData = {
labels: [
/*(略)*/
],
datasets: [
{
type: 'line', // 追加
label: 'sample-line',
data: [
/*(略)*/
],
borderColor : "rgba(254,97,132,0.8)",
backgroundColor : "rgba(254,97,132,0.5)",
},
{
type: 'bar', // 追加
label: 'sample-bar',
data: [
/*(略)*/
],
borderColor : "rgba(54,164,235,0.8)",
backgroundColor : "rgba(54,164,235,0.5)",
},
],
};
</script>
こうすると、こんなグラフができあがります。
縦軸の設定を変更する
が、データのスケールが大きくずれている!ということ、よくありますよね。(今回は見やすくするためあえて近づけています)複合チャートでなくても必要になることがありますが。そこで、それぞれのデータを別のスケールで表示してみます。ここがちょっとややこしかったです。
チャート全体のオプションに yAxes
今度はチャート全体のオプションに、下記のように、yAxes を設定します。複数設定して、それぞれに、ID を与えているのがポイントです。
<script>
var complexChartOption = {
responsive: true,
scales: {
yAxes: [{
id: "y-axis-1", // Y軸のID
type: "linear", // linear固定
position: "left", // どちら側に表示される軸か?
ticks: { // スケール
max: 0.2,
min: 0,
stepSize: 0.1
},
}, {
id: "y-axis-2",
type: "linear",
position: "right",
ticks: {
max: 1.5,
min: 0,
stepSize: .5
},
}],
}
};
</script>
データセットのオプションに yAxisID
今度はデータセット。各データセットが、先程作った2つの軸のうち、どちらの軸に属するデータなのかを指定するわけですね。
<script>
// とある4週間分のデータログ
var barChartData = {
labels: [
/*(略)*/
],
datasets: [
{
type: 'line',
label: 'sample-line',
data: [
/*(略)*/
],
borderColor : "rgba(254,97,132,0.8)",
backgroundColor : "rgba(254,97,132,0.5)",
yAxisID: "y-axis-1", // 追加
},
{
type: 'bar',
label: 'sample-bar',
data: [
/*(略)*/
],
borderColor : "rgba(54,164,235,0.8)",
backgroundColor : "rgba(54,164,235,0.5)",
yAxisID: "y-axis-2", // 追加
},
],
};
</script>
こうすると、こんなグラフができあがります。
あるとキレイになる欲張りオプション
ひとまず複合チャートになりましたが、まだあまり美しくないので、もう少しオプションを加えてみます。
ラインチャートを中抜きに
ラインだけにするのに fill:false
とします。実はよく見るとポインタの中身が抜けていたので、それも追加します。
<script>
datasets: [
{
type: 'line',
label: 'sample-line',
data: [
/*(略)*/
],
borderColor : "rgba(254,97,132,0.8)",
// 削除 backgroundColor : "rgba(254,97,132,0.5)",
pointBackgroundColor : "rgba(254,97,132,0.8)", // 追加
fill: false, // 追加
yAxisID: "y-axis-1",
},
</script>
第2軸の横グリッドを非表示に
横グリッド線が、2つの軸両方に表示されていて等間隔になっていないので、第2軸のみ消します。
}, {
id: "y-axis-2",
type: "linear",
position: "right",
ticks: {
max: 1.5,
min: 0,
stepSize: .5
},
gridLines: { // このオプションを追加
drawOnChartArea: false,
},
}],
</script>
完成!
こんな感じにできましたーー!
最後に、全体のコードを載せておきます。
(HTMLもBODYも無いけど、動くので……)
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.bundle.min.js"></script>
<div class="container" style="width:100%">
<canvas id="canvas"></canvas>
</div>
<script>
window.onload = function() {
ctx = document.getElementById("canvas").getContext("2d");
window.myBar = new Chart(ctx, {
type: 'bar',
data: barChartData,
options: complexChartOption
});
};
</script>
<script>
// とある4週間分のデータログ
var barChartData = {
labels: ['8/26','8/27','8/28','8/29','8/30','8/31','9/1',
'9/2','9/3','9/4','9/5','9/6','9/7','9/8',
'9/9','9/10','9/11','9/12','9/13','9/14',
'9/15','9/16','9/17','9/18','9/19','9/20','9/21','9/22'
],
datasets: [
{
type: 'line',
label: 'sample-line',
data: ['0.155','0.118','0.121','0.068','0.083','0.060','0.067',
'0.121','0.121','0.150','0.118','0.097','0.078','0.127',
'0.155','0.140','0.101','0.140','0.041','0.093','0.189',
'0.146','0.134','0.127','0.116','0.111','0.125','0.116'
],
borderColor : "rgba(254,97,132,0.8)",
pointBackgroundColor : "rgba(254,97,132,0.8)",
fill: false,
yAxisID: "y-axis-1",// 追加
},
{
type: 'bar',
label: 'sample-bar',
data: ['0.3','0.1','0.1','0.3','0.4','0.2','0.0',
'0.2','0.3','0.11','0.5','0.2','0.5','0.4',
'0.0','0.3','0.7','0.3','0.6','0.4','0.9',
'0.7','0.4','0.8','0.7','0.4','0.7','0.8'
],
borderColor : "rgba(54,164,235,0.8)",
backgroundColor : "rgba(54,164,235,0.5)",
yAxisID: "y-axis-2",
},
],
};
</script>
<script>
var complexChartOption = {
responsive: true,
scales: {
yAxes: [{
id: "y-axis-1",
type: "linear",
position: "left",
ticks: {
max: 0.2,
min: 0,
stepSize: 0.1
},
}, {
id: "y-axis-2",
type: "linear",
position: "right",
ticks: {
max: 1.5,
min: 0,
stepSize: .5
},
gridLines: {
drawOnChartArea: false,
},
}],
}
};
</script>