LoginSignup
5
6

More than 3 years have passed since last update.

Chart.jsを使用して複数軸のグラフを表示する(Javascript)

Last updated at Posted at 2020-02-11

はじめに

やりたいこと

<グラフ表示>
・現在日付から過去1カ月のデータを取得する。
・取得したデータをchart.jsにてグラフ表示する。
(X軸:日付、Y軸1-棒グラフ:Qiita-View数、Y軸2-折れ線グラフ:Qiitaいいね・ストックの合計)

<テーブル>
・取得したデータの中で最新日付のデータをテーブルを表示する。

使用技術

  • Javascript
  • Chart.js

デモサイト

デモサイト

※これをみると、投稿がまったく見られないなんてことはなく、毎日少なからずViewがあるんだなぁと思います。(さすがQiita)

1.png
2.png

コード・ポイント

  • グラフの描画部分
sample.js
// グラフを描画する
var ctx = document.getElementById("canvas").getContext("2d");
window.myChart = new Chart(ctx, {
  type: 'bar',
  data: barChartData,            //グラフデータをセット
  options: complexChartOption    //データオプションをセット
});
  • グラフデータのセット
sample.js
// グラフデータのセット
var barChartData = {
  labels: labelData,   //ラベルデータのセット(日付)
  datasets: [
    {
      type: 'line',
      label: 'Total-Likes/Stocks',
      data: lineData,     //lineデータのセット(LIKES+STOCKSの合計)
      borderColor: "rgba(060,179,113,0.8)",
      pointBackgroundColor: "rgba(060,179,113,0.8)",
      fill: false,
      yAxisID: "y-axis-1",
    },
    {
      type: 'bar',
      label: 'Total Views',
      data: barData,       //barデータのセット(VIEWSの合計)
      borderColor: "rgba(54,164,235,0.8)",
      backgroundColor: "rgba(54,164,235,0.5)",
      yAxisID: "y-axis-2",
    },
  ],
};
  • グラフオプションの設定 ticksは取得できた値に応じて、動的に算出する。
sample.js
// グラフオプションの設定
var complexChartOption = {
  responsive: true,
  scales: {
  yAxes: [
    {
      id: "y-axis-1",
      type: "linear",
      position: "left",
      ticks: {
        max: setgoodsMax,     //lineデータのメモリ最大値をセット
        min: setgoodsMin,     //lineデータのメモリ最小値をセット
        stepSize: 10          //lineデータのメモリ幅をセット
      },
    },
    {
      id: "y-axis-2",
      type: "linear",
      position: "right",
      ticks: {
        max: setviewsMax,     //barデータのメモリ最大値をセット
        min: setviewsMin,     //barデータのメモリ最小値をセット
        stepSize: 1000        //barデータのメモリ幅をセット
      },
      gridLines: {
      drawOnChartArea: false,
      },
    }
  ],
};
  • 全体のコード

全体のコード
jsgraph.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>Qiita Item Get Graph Display</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
  </head>

  <body onload="getData()">
    <div class="container">
      <br>
      <h3>Qiitaデータグラフ表示</h3>
      <br>
      <div class="container">
        <canvas id="canvas"></canvas>
      </div>
      <div class="container">
        <div id="result"></div>
      </div>
    </div>

    <script src="https://code.jquery.com/jquery-2.1.1.js" integrity="sha256-FA/0OOqu3gRvHOuidXnRbcmAWVcJORhz+pv3TX2+U6w=" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.bundle.min.js"></script>

    <script>
      function getData(){

        var qiitadata = [];

        // 現在日付の設定
        var date = new Date();
        var yyyy = date.getFullYear();
        var mm = toDoubleDigits(date.getMonth() + 1);
        var dd = toDoubleDigits(date.getDate());
        var yyyymmdd = yyyy + mm + dd;
        var hyphendate = yyyy + "-" + mm + "-" + dd;

        // 1桁の数字を0埋めで2桁にする
        function toDoubleDigits(num){
          num += "";
          if (num.length === 1) {
            num = "0" + num;
          }
          return num;
        };

        // DB情報の取得
        var request = new XMLHttpRequest();
        request.open('GET', 'xxxxxxxxxxxxxxxxxxxx.php?setdate=' + yyyymmdd, true);
        request.responseType = 'json';

        request.onload = function () {
          qiitadata = this.response;
          drawGraph(qiitadata);                // グラフの描画
          drawTable(qiitadata, hyphendate);    // テーブルの描画
        };

        request.send();

      };

      // グラフの描画
      function drawGraph(qiitadata) {

        var nowdate;
        var sumviews = 0;
        var sumgoods = 0;
        var labelData = [];
        var lineData = [];
        var barData = [];

        // 取得データをループして、グラフ描画データにセットする
        for(var i = 0; i < qiitadata.length; i++){

          // 初回は日付のセット
          if(i == 0){
            nowdate = qiitadata[i].setdate;
          }else{
            // 日付が変わったとき
            if(nowdate != qiitadata[i].setdate){
              //データをセット
              labelData.push(nowdate);
              lineData.push(sumgoods);
              barData.push(sumviews);
              //日付のセットと合計初期化
              nowdate = qiitadata[i].setdate;
              sumgoods = 0;
              sumviews = 0;
            };
          };

          sumgoods = sumgoods + Number(qiitadata[i].likes) + Number(qiitadata[i].stocks);
          sumviews = sumviews + Number(qiitadata[i].views);

          // ループの最後の処理
          if(i == (qiitadata.length - 1)){
            labelData.push(nowdate);
            lineData.push(sumgoods);
            barData.push(sumviews);
          }

        };

        // セットされたデータからticksを算出
        var goodsMax = Math.max.apply(null, lineData);
        var setgoodsMax = goodsMax + 10;
        do {
          setgoodsMax += 1;
        } while ("00" != String(setgoodsMax).substr(-2,2));

        var goodsMin = Math.min.apply(null, lineData);
        var setgoodsMin = goodsMin - 10;
        do {
          setgoodsMin -= 1;
        } while ("00" != String(setgoodsMin).substr(-2,2));

        var viewsMax = Math.max.apply(null, barData);
        var setviewsMax = viewsMax + 1000;
        do {
          setviewsMax += 1;
        } while ("000" != String(setviewsMax).substr(-3,3));

        var viewsMin = Math.min.apply(null, barData);
        var setviewsMin = viewsMin - 1000;
        do {
          setviewsMin -= 1;
        } while ("000" != String(setviewsMin).substr(-3,3));

        // グラフデータのセット
        var barChartData = {
          labels: labelData,
          datasets: [
            {
              type: 'line',
              label: 'Total-Likes/Stocks',
              data: lineData,
              borderColor: "rgba(060,179,113,0.8)",
              pointBackgroundColor: "rgba(060,179,113,0.8)",
              fill: false,
              yAxisID: "y-axis-1",
            },
            {
              type: 'bar',
              label: 'Total Views',
              data: barData,
              borderColor: "rgba(54,164,235,0.8)",
              backgroundColor: "rgba(54,164,235,0.5)",
              yAxisID: "y-axis-2",
            },
          ],
        };

        // グラフオプションの設定
        var complexChartOption = {
          responsive: true,
          scales: {
            yAxes: [
              {
                id: "y-axis-1",
                type: "linear",
                position: "left",
                ticks: {
                  max: setgoodsMax,
                  min: setgoodsMin,
                  stepSize: 10
                },
              },
              {
                id: "y-axis-2",
                type: "linear",
                position: "right",
                ticks: {
                  max: setviewsMax,
                  min: setviewsMin,
                  stepSize: 1000
                },
                gridLines: {
                  drawOnChartArea: false,
                },
              }
            ],
          }
        };

        // グラフを描画する
        var ctx = document.getElementById("canvas").getContext("2d");
        window.myChart = new Chart(ctx, {
          type: 'bar',
          data: barChartData,
          options: complexChartOption
        });

      };

      // テーブルの描画
      function drawTable(qiitadata, hyphendate) {

        // 配列の中の最大値を取得する
        var maxno = Math.max.apply(null, qiitadata.map(function(o){return o.no;}));
        // console.log(maxno);

        var sum_view = 0;
        var sum_like = 0;
        var sum_stock = 0;

        var html = '<br><h3>Qiita記事一覧(' + hyphendate + '時点)</h3><br>' +
                  '<table class="table">' +
                  '<thead class="thead-dark">' +
                  '<tr><th scope="col">No</th><th scope="col">タイトル</th><th scope="col">VIEWS</th><th scope="col">LIKES</th><th scope="col">STOCKS</th><th scope="col">LIKE率</th><th scope="col">STOCK率</th></tr></thead><tbody>'

        // 取得データをループして、グラフ描画データにセットする
        for(var i = 0; i < qiitadata.length; i++){
          // 本日日付になったら、格納処理
          if(qiitadata[i].setdate == hyphendate){

            html +=
              '<tr>' +
              '<th scope="row">' + (maxno + 1 - Number(qiitadata[i].no)) + '</th>' +
              '<td><a href="' + qiitadata[i].url + '" target="_blank">' + qiitadata[i].title + '</a></td>' +
              '<td>' + qiitadata[i].views + '</td>' +
              '<td>' + qiitadata[i].likes + '</td>' +
              '<td>' + qiitadata[i].stocks + '</td>' +
              '<td>' + qiitadata[i].per_like + '</td>' +
              '<td>' + qiitadata[i].per_stock + '</td>' +
              '</tr>';

              sum_view += Number(qiitadata[i].views);
              sum_like += Number(qiitadata[i].likes);
              sum_stock += Number(qiitadata[i].stocks);

          };
        };

        // html に合計を設定し、書き出し
        html +=
          '<tr class="table-warning">' +
          '<th scope="row">計</th>' +
          '<td></td>' +
          '<td>' + sum_view + '</td>' +
          '<td>' + sum_like + '</td>' +
          '<td>' + sum_stock + '</td>' +
          '<td>' + '' + '</td>' +
          '<td>' + '' + '</td>' +
          '</tr>' +
          '</tbody></table>';

        var result = $("#result");
        result.empty();
        result.append(html);
      };
    </script>
  </body>
</html>

まとめ

参考URL

5
6
0

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