以前に紹介した、Chart.js で経過時間のグラフを作った際の覚書です。

 

 

過去に2回程度、この Chart.js に関する記事を書いているのですが、そもそもなんでChart.js を学習する必要があったのかと言うと、過去記事でも書いているように、PCのベンチマーク結果をこのブログで表示させたい、というのがその発端でした。

 

Chart.js で経過時間のグラフとは?

ここで、経過時間に付いてのグラフはどんなのかと言うと、それは下の例を見ていただいたほうが早いかもしれません。

 

これは横棒グラフ(type: 'horizontalBar')なんですが、経過時間のグラフとは、横軸に時間を使ったグラフのことを指しています。

なんだ、そんなの簡単じゃないか、と思われるかもしれませんが、Chart.js のドキュメントを読む限りはこのタイプのグラフを表示させる簡単な方法を見つけることができませんでした。

 

軸目盛りのタイプを ”time” にする方法

ただ、次のような例はあります。

これは折線タイプのグラフで、CPU温度を表しているのですが、x軸に時間軸(分単位)、y軸に温度(℃)をとっています。このとき、options.scales.xAxes.type = 'time' とすることで このような、直線的な時間軸を表示させる分には問題なくできます。

以下が、そのコードになります。

var ctx = document.getElementById("hf4zsup7").getContext("2d");
var myChart = new Chart(ctx, {
  type: "line",
  data: {
    labels: ["00:30", "01:00", "01:30", "2:00", "02:30", "03:00", "03:30", "04:00", "04:30", "05:00", "05:30", "06:00", "06:30", "07:00"],
    datasets: [{
      label: "CPU 1",
      data: [28, 45, 63, 36, 27, 69, 48, 29, 38, 52, 88, 21, 47, 35],
      borderColor: "rgb(255, 99, 132)",
      backgroundColor: "rgba(255, 99, 132, 0.2)"
    }, {
      label: "CPU 2",
      data: [11, 58, 23, 44, 19, 87, 65, 11, 58, 23, 44, 19, 87, 65],
      borderColor: "rgb(54, 162, 235)",
      backgroundColor: "rgba(54, 162, 235, 0.2)"
    }]
  },
  options: {
    elements: {
      line: {
        tension: 0
      }
    },
    scales: {
      xAxes: [{
        type: 'time',
        time: {
          parser: "mm:ss", //<- use 'parser'
          unit: 'minute',
          unitStepSize: 1,
          displayFormats: {
            'minute': 'mm',
          }
        }
      }],
      yAxes: [{
        ticks: {
          beginAtZero: true
        }
      }]
    }
  }
});

 

また、次のような表現も可能です。

こちらは、y軸に時間、x軸にラベルを配置しています。

でもこれはこれで、違和感が大いにありますし、このグラフの typebar にした途端に表示できなく なります。

var ctx = document.getElementById('a63ej0u5').getContext('2d');
var chart = new Chart(ctx, {
  type : 'line',
  data : {
    labels : ['Ryzen5 3600 + GTX1660Ti', 'Ryzen7 2700x + GTX660Ti', 'Core i7-4770 + GTX660' ],
    datasets : [{
        label : 'duration',
      data : ["9:14.940", "8:14.060", "18:36.050"],
      borderColor: 'rgba(0, 99, 132, 0.6)',
      pointBackgroundColor: 'rgba(0, 99, 132, 0.6)',
    }]
  },
  options : {
    scales : {
      yAxes : [{
        type : 'time',
        time : {
          parser: 'm:s.SSS',
          unit : 'seconds',
          unitStepSize : 240,
          min: '0:00.000',
          max: '20:00.000',
          displayFormats : {
            'seconds' : 'mm.ss'
          }
        },
      }]
    },

    title : {
      display : true,
      position : 'top',
      text : 'Blender2.8 レンダリング時間'
    },
    elements : {
      line : {
        tension : 0
      }
    }
  }
});

 

Chart.js で経過時間のグラフを表示させる方法

Chart.js でも time を使って軸を設定してもうまくいかないので、発想を変えて、経過時間を数値化してグラフを作成することにしました。

実際のコードを見ながら説明します。

var ar = [
    moment("1970-01-01 00:09:14.940 +0000", "YYYY-MM-DD HH:mm:ss.SSS Z").format('x'), // 554940
    moment("1970-01-01 00:08:14.060 +0000", "YYYY-MM-DD HH:mm:ss.SSS Z").format('x'), // 494060
    moment("1970-01-01 00:18:36.050 +0000", "YYYY-MM-DD HH:mm:ss.SSS Z").format('x') // 1116050
  ];
  var ctx = document.getElementById("blender_rendering").getContext("2d");
  var chart = new Chart(ctx, {
    type: "horizontalBar",
    data: {
      labels: ["経過時間(分)", ],
      datasets: [{
        label: "Ryzen5 3600 + GTX1660Ti",
        data: [ar[0], ],
        backgroundColor: "rgba(255, 0, 0, 0.6)",
        borderWidth: 0
      }, {
        label: "Ryzen7 2700X + GTX660Ti",
        data: [ar[1], ],
        backgroundColor: "rgba(255, 102, 0, 0.6)",
        borderWidth: 0
      }, {
        label: "Core i7-4770 + GTX660",
        data: [ar[2], ],
        backgroundColor: "rgba(0, 0, 255, 0.6)",
        borderWidth: 0
      }, ]
    },
    options: {
      maintainAspectRatio: false,
      title: {
        fontSize: 18,
        display: true,
        position: "top",
        text: "Blender 2.8 Cycles 標準 4608px x 3456px : CPUレンダリング"
      },
      tooltips: {
        callbacks: {
          title: function(tooltipItem, data) {
            console.log(data);
            return data.labels[0];
          },
          label: function(tooltipItem, data) {
            let value = Number(tooltipItem.value);
            let index = tooltipItem.datasetIndex;
            let label = data.datasets[index].label;
            let duration = moment(value, "x").format("m 分 s 秒 SSS");
            return label + ":  " + duration;
          }
        },
        position: "nearest"
      },
      scales: {
        xAxes: [{****
          ticks: {
            beginAtZero: 1,
            stepSize: 300000,
            min: 0,
            callback: function(label, index, labels) {
              let duration = moment(label, "x").format("mm:ss");
              return duration;
            }
          }
        }]
      },
    }
  });

 

Moment.js で時間を数値に

ここでは、時間のフォーマットや変換にMoment.js を使用しています。

コードを見ていただいたらわかるように、元のデータ、mm:ss.SSS (分:秒.ミリ秒) の時間フォーマットを UNIX時間に置き換えてグラフを作成し、グラフの目盛りやツールチップを UNIX時間から時間フォーマットに置き換え直す方法です。

var ar = [
  moment("1970-01-01 00:09:14.940 +0000", "YYYY-MM-DD HH:mm:ss.SSS Z").format('x'), // 554940
  moment("1970-01-01 00:08:14.060 +0000", "YYYY-MM-DD HH:mm:ss.SSS Z").format('x'), // 494060
  moment("1970-01-01 00:18:36.050 +0000", "YYYY-MM-DD HH:mm:ss.SSS Z").format('x') // 1116050
];

UNIX時間とは、1970年1月1日の午前0時0分0秒からの累積秒数を指します。この例の場合は、UNIX時間にミリ秒を含めて数値化させています。

moment( 時刻文字列, フォーマット).format( フォーマット指定文字列 )

moment.js では現在のタイムゾーン、日本(JST)の場合は GMT+0900 (グリニッジ標準時 + 9時間) が考慮されるために、タイムゾーンをUTC(+0000)に指定しています。

なので、この例では本当の計測時間は、"00:08:14.060" であったり "00:18:36.050" であったりするのですが、上の理由から "1970-01-01 00:18:36.050 +0000" のようにしています。

 

数値から時間への変換

また、グラフ上の目盛りの単位、マウスをグラフ上に Hobber させたときのツールチップについては、再度数値から時刻への変換を行います。

ツールチップについては、moment(value, "x").format("m分 s秒 SSS) で、
目盛りについては、moment(label, "x").format("mm:ss") でそれぞれ時間文字列に置き換えています。

 

まとめ

もともと、先のベンチマークの記事のために Chart.js を選定したものの、経過時間のグラフを作成する部分で躓いてしまいましたが、いろいろ工夫してみることで表示させることができるようになりました。

とはいっても、WordPress では標準では直接記事上にスクリプトを書くことはできないので、そこはちょっと工夫がいります。私の場合は、ちょっとしたショートコードを使ったプラグインを作成しました。

また、ツールチップや目盛りのフォーマットについては、過去記事を参照してください。


0件のコメント

コメントを残す

メールアドレスが公開されることはありません。