Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
193
Help us understand the problem. What is going on with this article?
@kd9951

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

More than 3 years have passed since last update.

複合チャートが描きたい

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>

193
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
kd9951
インフラからデザインまで。ワンストップでWEBアプリケーション開発しているエンジニア。メインはPHP/Laravelでの業務系システム開発。WordpressやAugnlarあたりも守備範囲。自称「穴埋め係」でGoogleやQiitaに無かった記事を書くことが多いので、誰得なマニアックな記事が多いです(*´ω`*)    園芸が好きで「多肉植物図鑑PUKUBOOK」を制作し編集長をしています。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
193
Help us understand the problem. What is going on with this article?