Chartjs-How to chart detected activities on the hour using Chart.js

0👍

If I interpreted your question correctly, here is an option that you could use. Before jumping straight to the example, let me explain the approach.

First, your requirement is a bit challenging because this would require using a “category” scale on the y-axis along with a “time” scale on the x-axis. This is a challenge because line charts typically have a “category”, “linear”, or “time” x-axis and a numerical based scale (e.g. linear, logarithmic, etc.) on the y-axis.

Therefore, to overcome this, I had to use a “linear” scale on the y-axis but use some callbacks to make it appear as if it was actually a “category” scale. By the way, I tried adding a “category” scale on the y-axis, but could never get a chart to render (so I don’t think it is possible).

Since you did not provide an exact example of how your data is stored, I had to make some assumptions for my mock data. Regardless of how it is actually stored, the approach would be to process the data to convert it into a format that chart.js can understand. In my example, I have done this using a function called prepareDataForChart.

Here is the final chart configuration.

var myChart = new Chart(ctx, {
  type: 'line',
  data: {
    datasets: [{
      label: "Object 1",
      fill: false,
      borderColor: window.chartColors.red,
      backgroundColor: window.chartColors.white,
      pointRadius: 0,
      steppedLine: true,
      data: prepareDataForChart(mockedActivityData),
    }]
  },
  options: {
    responsive: true,
    title: {
      display: true,
      text: 'Object Activity State Over Time'
    },
    tooltips: {
      mode: 'index',
      intersect: false,
      callbacks: {
        // since we mapped the eventState to a numerical value,
        // let's convert that back to a text value when the tooltip
        // is displayed
        label: function(tooltipItem, data) {
          if (tooltipItem.yLabel === 1) {
            return 'Normal';
          } else if (tooltipItem.yLabel === 2) {
            return 'Active';
          }
        }
      }
    },
    scales: {
      xAxes: [{
       type: 'time',
        time: {
          unit: 'minute',
          displayFormats: {
            minute: 'lll',
          },
          tooltipFormat: 'lll',
        },
        scaleLabel: {
          display: true,
          labelString: 'Time',
        }
      }],
      yAxes: [{
        scaleLabel: {
          display: true,
          labelString: 'Activity State',
        },
        ticks: {
          min: 0,
          max: 3,
          stepSize: 1,
          // since we mapped the eventState to a numerical value,
          // let's convert that back to a text value to display 
          // on the y-axis (and also hide all other tick labels)
          callback: function(value, index, values) {
            if (value === 2) {
              return 'Active';
            } if (value === 1) {
              return 'Normal';
            } else {
              return ' ';
            }
          },
        },
      }]
    }
  }
});

And because it’s always nice to be able to actually see something, here is a codepen example.

Leave a comment