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.