LoginSignup
221
213

More than 5 years have passed since last update.

chart.js で複数軸の複合グラフを描く

Last updated at Posted at 2016-09-23

複合チャートが描きたい

1.png

棒グラフと折れ線グラフを1つのチャート内に表示したりするアレが描きたかった。英語ではMixed Chartって言うんですかね。Google Chartではわりと以前からできていたようですが、Chart.jsでは、Ver.2.0(2016/04リリース)からの新機能だそうです。

4.png

このコンテンツでは、このグラフを作ります。

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つのファイルにまとめると、こんなグラフができあがります。

2.png

複合チャートにする

データセットオプションに 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>

こうすると、こんなグラフができあがります。

25.png

縦軸の設定を変更する

が、データのスケールが大きくずれている!ということ、よくありますよね。(今回は見やすくするためあえて近づけています)複合チャートでなくても必要になることがありますが。そこで、それぞれのデータを別のスケールで表示してみます。ここがちょっとややこしかったです。

チャート全体のオプションに 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>

こうすると、こんなグラフができあがります。

3.png

あるとキレイになる欲張りオプション

ひとまず複合チャートになりましたが、まだあまり美しくないので、もう少しオプションを加えてみます。

ラインチャートを中抜きに

ラインだけにするのに 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>

完成!

こんな感じにできましたーー!

4.png

最後に、全体のコードを載せておきます。
(HTMLもBODYも無いけど、動くので……)

complex-chart-sample.html

<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>

221
213
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
221
213