ChartJS timeline graph with events - chart.js

I am trying to build a graph that would ressemble the one in the screenshot : it is a timeline on which events are displayed.
But I need the spacing between events to correspond to actual time passing, therefore I believe I can not provide the events as X axis... so I really don't know what I should be looking at.

First, you need to define the xAxis as a time cartesian axis. Then you can define the data of your dataset as individual points through objects containing x and y properties.
Please note that Chart.js internally uses Moment.js for the functionality of the time axis. Therefore you should use the bundled version of Chart.js that includes Moment.js in a single file.
const img = new Image(16, 16);
img.src = 'https://i.stack.imgur.com/Q94Tt.png';
var ctx = document.getElementById('chart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
data: [
{ x: "2020-03-22", y: 0 },
{ x: "2020-04-01", y: 0 },
{ x: "2020-04-02", y: 0 },
{ x: "2020-04-03", y: 0 },
{ x: "2020-04-08", y: 0 },
{ x: "2020-04-12", y: 0 },
{ x: "2020-04-15", y: 0 }
],
pointStyle: img,
borderWidth: 1
}]
},
options: {
legend: {
display: false
},
scales: {
yAxes: [{
ticks: {
display: false,
},
gridLines: {
display: false
}
}],
xAxes: [{
type: 'time',
time: {
unit: 'day',
tooltipFormat: 'MMM DD'
},
gridLines: {
display:false
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
<canvas id="chart" height="28"></canvas>

Related

chart.js horizontal stack bar not showing expcected result

i have a project in real time calculation project does not stack correctly ,i have 3 dataset stack one by one but it shows only two data in my chart
<div class="graph_container">
<canvas ref="myChart" width="400" height="400"></canvas>
</div>
Option for horizontal stack bar format with time
var options={
responsive:true,
maintainAspectRatio: false,
indexAxis: 'y',
scales: {
x: {
offset: true,
stacked: true,
type: 'time',
time: {
unit:'hour'
},
min: moment(String(todayStartTime)),
max: moment(String(todayEndTime))
// max: moment().add(8, 'hours')
},
y: {
stacked: true,
offset: true
}
}
}
My Dataset
const data = {
datasets: [
{
label: "T1"+moment(todayStartTime).add(0.5,'hours'),
data: [
{
x: moment(todayStartTime).add(0.5,'hours'),
y: 0
},
],
backgroundColor: "red"
},
{
label: "T2"+moment(todayStartTime).add(2,'hours'),
data: [{
x: moment(todayStartTime).add(2,'hours'),
y: 0
}],
backgroundColor: "blue"
},
{
label: "T3"+moment(todayStartTime).add(3,'hours'),
data: [
{
x: moment(todayStartTime).add(3,'hours'),
y: 0
}],
backgroundColor: "orange"
},
]
};
Chart js
var $vm=this;
const ctx =this.$refs.myChart;
var todayStartTime=new moment('2022-10-19 08:00:00 am')
var todayEndTime=new moment('2022-10-19 03:00:00 pm')
const config = {
type: 'bar',
data,
options
};
new Chart(ctx,config);
Output (First Dataset only Correct)
it showing only first dataset is correct other dataset wrong and some missing
This is because you have a stacked x axis, this means that instead of the value starting at the origin it starts where the first bar ends. To resolve this issue you need to set the options.scales.x.stacked to false or dont set it since false is the default.
Example:
var todayStartTime = new moment('2022-10-19 08:00:00');
var todayEndTime = new moment('2022-10-19 15:00:00');
var options = {
responsive: true,
maintainAspectRatio: false,
indexAxis: 'y',
scales: {
x: {
offset: false,
type: 'time',
time: {
unit: 'hour'
},
min: todayStartTime,
max: todayEndTime
},
y: {
stacked: true,
offset: true
}
}
};
const data = {
datasets: [{
label: "T1" + moment(todayStartTime).add(0.5, 'hours'),
data: [{
x: moment(todayStartTime).add(0.5, 'hours'),
y: 0
}],
backgroundColor: "red"
},
{
label: "T2" + moment(todayStartTime).add(2, 'hours'),
data: [{
x: moment(todayStartTime).add(2, 'hours'),
y: 0
}],
backgroundColor: "blue"
},
{
label: "T3" + moment(todayStartTime).add(3, 'hours'),
data: [{
x: moment(todayStartTime).add(3, 'hours'),
y: 0
}],
backgroundColor: "orange"
},
]
};
const ctx = document.getElementById('myChart').getContext('2d');
const config = {
type: 'bar',
data,
options
};
new Chart(ctx, config);
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.9.1/dist/chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/moment#2.29.4/moment.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment#1.0.0/dist/chartjs-adapter-moment.min.js"></script>
<canvas id="myChart" width="600" height="400" />
Credits go to Stockinail that answered this question already on github: https://github.com/chartjs/Chart.js/issues/10815

chartjs : uncaught exception: 0 and X are too far apart with stepSize of Y

I am plotting data on a graph with chartjs. It used to work but I don't know why I am continuously getting uncaught exception: 0 and 1587533402000 are too far apart with stepSize of 1 hour, although neither 0 nor 1587533402000 are part of the data I plot.
Here is how I plot the graph :
var chart_temperature = new Chart(ctx_temperature, {
// The type of chart we want to create
type: 'line',
// The data for our dataset
data: {
labels: timeXValues,
fill: false, // no inner color
datasets: [{
label: 'Temperature',
borderColor: 'rgb(255, 99, 132)',
data: temperatureData
}]
},
// Configuration options go here
options: {
responsive: true,
layout: {
padding: {
bottom: 50
}
},
elements: {
point: {
radius: 0 // don't show points
},
line: {
fill: false
}
},
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'hour',
displayFormats: {
hour: 'DD/MM/YYYY HH:mm'
}
},
ticks: {
beginAtZero: false // tried true, and also removed all this as it used to be
}
}],
yAxes: [{
scaleLabel: {
display: true,
labelString: 'T°C'
}
}]
},
showLines: true, // the points will be connected
// Optimization
animation: {
duration: 0 // general animation time
},
hover: {
animationDuration: 0 // duration of animations when hovering an item
},
responsiveAnimationDuration: 0 // animation duration after a resize
}
});
Why is chartjs using 0 whereas the chart is not starting at 0 ? Where should I look at ?
Any help appreciated :-)
Edit :
Commenting the following line (in scales.xAxes) makes the chart displayed :
// type: 'time',
But the X Axis becomes then useless since timestamps are displayed.
A genius idea finally spurted! Searching against are too far apart with stepSize in chartjs git repository showed that time scale min option was wrongly set to 0.
Adding these min max to time option of xAxes solved the issue.
And even as time min max options are deprecated, ticks.min and ticks.max should be used:
ticks: {
min: startTimestamp,
max: endTimestamp
}
For me, I needed to update my type time to "minute" instead of "second".
xAxes: [ {
type: 'time',
time: {
unit: 'minute'
},
In my case, that because the data from x is not 'int' but 'string'.
data from Backend:
data: [{
x: "1626414792000", //1626414792000
y: 2
}, {
x: 1626414873000, // 14:00:00
y: 3
}, {
x: 1626415500000, // 13:00:00
y: 5
}]
}],
Then, I parse x data before chart.js use it.
My full code:
var obj = {
type: 'line',
data: {
datasets: [{
label: 'First dataset',
data: [{
x: "1626414792000",
y: 2
}, {
x: 1626414873000,
y: 3
}, {
x: 1626415500000,
y: 5
}]
}],
},
options: {
title: {
text: 'Chart',
display: true,
},
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'minute',
/* parsing x data before chart.js use it */
parser: function(dt){
console.log(dt)
return parseInt(dt);
}
}
}]
}
}
}
In my case, the issue happened when zooming.
It was caused by wrong properties of the zoom plugin option used with a chart type 'time'. The following works options works fine:
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
yAxes: [{
ticks: {
suggestedMin: 0,
},
}],
xAxes: [{
type: 'time',
time: {
unit: 'day',
tooltipFormat: 'MMM DD YYYY',
},
}],
},
plugins: {
zoom: {
pan: {
enabled: true,
mode: 'xy'
},
zoom: {
enabled: true,
mode: 'xy',
}
}
}
}

Disable display of x and y values on ChartJS

For some reasons I have X and Y values showing up on my line chart as follows, but they are unexpected.
<canvas id="chartTimeline" height="28"></canvas>
<script>
const img = new Image(16, 16);
img.src = 'https://i.stack.imgur.com/Q94Tt.png';
var ctx = document.getElementById('chartTimeline').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
data: [
{ x: "2020-03-22", y: 0 },
{ x: "2020-04-01", y: 0 },
{ x: "2020-04-02", y: 0 },
{ x: "2020-04-03", y: 0 },
{ x: "2020-04-08", y: 0 },
{ x: "2020-04-12", y: 0 },
{ x: "2020-04-15", y: 0 }
],
pointStyle: img,
borderWidth: 1
}]
},
options: {
legend: {
display: false
},
scales: {
yAxes: [{
ticks: {
display: false,
},
gridLines: {
display: false
}
}],
xAxes: [{
type: 'time',
time: {
unit: 'day',
tooltipFormat: 'MMM DD'
},
gridLines: {
display:false
}
}]
}
}
});</script>
As per my understanding of chartJS options, theses values should not appear. There are no errors popping in the console.
I wonder, what is this called ? Why is it being displayed ? How can I disable it ?
The problem was the datalabels plugin, it was generating these values automatically.

chart.js automatic x axis distributed in time milliseconds

I'm building a local html file that will generate some graphs using chartjs when offline. I'm just testing some example data I have.
See fiddle below.
http://jsfiddle.net/joshmoto/0odcemL7/
The issue is, i've set 8 points of data for each dataset, but the graph is only outputting 2 points for each dataset.
I need my x axis to display a automatic time grid distributed in seconds. My time data consists millisecond data, but my x axis grid needs to show steps in seconds. But my points must remain accurately positioned on the graph within the steps as the data is milliseconds.
.
var ctx = document.getElementById('log_chart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
label: 'Engine Speed',
backgroundColor: '#ff0000',
borderColor: '#ff0000',
fill: false,
data: [{
t: new Date(0.37),
y: 2640
}, {
t: new Date(0.85),
y: 2560
}, {
t: new Date(1.33),
y: 2560
}, {
t: new Date(1.78),
y: 2560
}, {
t: new Date(2.23),
y: 2680
}, {
t: new Date(2.7),
y: 2920
}, {
t: new Date(3.16),
y: 3200
}, {
t: new Date(3.63),
y: 3520
}]
}, {
label: 'Mass Air Flow - Sensor',
backgroundColor: '#00FFFF',
borderColor: '#00FFFF',
fill: false,
data: [{
t: new Date(0.02),
y: 19.58
}, {
t: new Date(0.45),
y: 16.28
}, {
t: new Date(0.92),
y: 8.56
}, {
t: new Date(1.39),
y: 8.47
}, {
t: new Date(1.86),
y: 23.36
}, {
t: new Date(2.33),
y: 45.78
}, {
t: new Date(2.78),
y: 56.03
}, {
t: new Date(3.23),
y: 62.36
}]
}],
},
options: {
scales: {
// xAxes: [{
// type: 'time',
// displayFormats: {
// quarter: 'ss.SSS'
// },
// time: {
// unit: 'second'
// }
// }]
}
}
});
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.8.0/dist/Chart.min.js"></script>
<div class="container">
<div class="col-12 mt-3 mb-3">
<canvas id="log_chart" width="600" height="200"></canvas>
</div>
</div>
Basically the data works like this...
t is the x axis but in time format seconds.
y is the value ranging from 0 - 5000
I'm trying my hardest to follow the docs but struggling to work this one out, I can't see anything obvious. If anyone can help out that would be awesome.
I think you need to provide more information to Chart.js so that it knows what to do with the X-Axis. On previous projects, I've given a labels property within the data.
Example -
// document ready
(function ($) {
var ctx = document.getElementById('log_chart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: [1, 2, 3, 4, 5, 6, 7, 8],
datasets: [
{
label: 'Engine Speed',
backgroundColor: '#ff0000',
borderColor: '#ff0000',
fill: false,
data: [2640,2560,2560,2560, 2680, 2920, 3200, 3520]
},
{
label: 'Mass Air Flow - Sensor',
backgroundColor: '#00FFFF',
borderColor: '#00FFFF',
fill: false,
data: [19.58, 16.28, 8.56, 8.47, 23.36, 45.78, 56.03, 62.36]
}
],
},
options: {
scales: {
yAxes: [{
stacked: false
}],
}
}
});
})(jQuery);
So the labels property can then fill your X axis, and your data sets just plot the raw data onto the graph. The problem you'll run into with this kind of dataset is that the sensors readings are significantly lower than the engine speed, so not well represented on the chart. You'll have to work out some kind of way of normalising this data so it can be properly represented, e.g. adding a multiply to the mass airflow sensor readings.
I figured out using x axis type: linear; and removed the date functionality and just used the raw millisecond data in x rather than t.
See working example below.
var ctx = document.getElementById('log_chart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
label: 'Engine Speed',
backgroundColor: '#ff0000',
borderColor: '#ff0000',
fill: false,
data: [{
x: 0.37,
y: 2640
}, {
x: 0.85,
y: 2560
}, {
x: 1.33,
y: 2560
}, {
x: 1.78,
y: 2560
}, {
x: 2.23,
y: 2680
}, {
x: 2.7,
y: 2920
}, {
x: 3.16,
y: 3200
}, {
x: 3.63,
y: 3520
}]
}, {
label: 'Mass Air Flow - Sensor',
backgroundColor: '#00FFFF',
borderColor: '#00FFFF',
fill: false,
data: [{
x: 0.02,
y: 19.58
}, {
x: 0.45,
y: 16.28
}, {
x: 0.92,
y: 8.56
}, {
x: 1.39,
y: 8.47
}, {
x: 1.86,
y: 23.36
}, {
x: 2.33,
y: 45.78
}, {
x: 2.78,
y: 56.03
}, {
x: 3.23,
y: 62.36
}]
}],
},
options: {
responsive: true,
title: {
display: true,
text: "Chart.js Time Scale"
},
scales: {
xAxes: [{
type: 'linear',
position: 'bottom'
}]
}
}
});
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.8.0/dist/Chart.min.js"></script>
<div class="container">
<div class="col-12 mt-3 mb-3">
<canvas id="log_chart" width="600" height="200"></canvas>
</div>
</div>

Order the Time Units on Y-axis + Chart Js

I have time on Y-axis and dates on X-axis. I have built the chart using chart.js and my chart looks as below.
But, as you can see my Y-axis is in reversed order. I don't know how to fix it. Please assist.
Here is my js
var s1 = {
label:'S1',
borderColor: '#33b5e5',
data: [
{ x: '2017-01-06 00:00:00', y: '2017-01-06 04:15:30' },
{ x: '2017-01-07 00:00:00', y: '2017-01-06 07:39:30' },
{ x: '2017-01-08 00:00:00', y: '2017-01-06 06:39:30' },
{ x: '2017-01-09 00:00:00', y: '2017-01-06 08:00:30' },
{ x: '2017-01-10 00:00:00', y: '2017-01-06 05:39:30' },
{ x: '2017-01-11 00:00:00', y: '2017-01-06 09:39:30' },
]
};
var ctx = document.getElementById('myChart').getContext('2d');
var chart = new Chart(ctx, {
type: 'line',
data: { datasets: [s1] },
options: {
legend: {
display: false
},
scales: {
xAxes: [{
type: 'time',
weight : 0 ,
time: {
unit:'day'
}
}],
yAxes: [{
type: 'time',
//type: 'linear',
reverse: false,
time: {
unit:'hour'
},
ticks: {
beginAtZero:true
}
}]
}
}
});
chart.canvas.parentNode.style.height = '380px';
chart.canvas.parentNode.style.width = '700px';
Please find the full code snippet in below link.
https://jsfiddle.net/sjabiulla/3d1tpwhy/1/
Chart.js 2.8.0 adds reverse support to time scales, although this doesn't appear to be documented anywhere except the release notes. Move reverse into the tick configuration and it should fix the problem:
yAxes: [{
ticks: {
reverse: true,
...
},
...
}]
Here's a working example:
var s1 = {
label: 'S1',
borderColor: '#33b5e5',
data: [{
x: '2017-01-06 00:00:00',
y: '2017-01-06 04:15:30'
},
{
x: '2017-01-07 00:00:00',
y: '2017-01-06 07:39:30'
},
{
x: '2017-01-08 00:00:00',
y: '2017-01-06 06:39:30'
},
{
x: '2017-01-09 00:00:00',
y: '2017-01-06 08:00:30'
},
{
x: '2017-01-10 00:00:00',
y: '2017-01-06 05:39:30'
},
{
x: '2017-01-11 00:00:00',
y: '2017-01-06 09:39:30'
},
]
};
var ctx = document.getElementById('myChart').getContext('2d');
var chart = new Chart(ctx, {
type: 'line',
data: {
datasets: [s1]
},
options: {
legend: {
display: false
},
scales: {
xAxes: [{
type: 'time',
weight: 0,
time: {
unit: 'day'
}
}],
yAxes: [{
type: 'time',
time: {
unit: 'hour'
},
ticks: {
reverse: true,
beginAtZero: true
}
}]
}
}
});
chart.canvas.parentNode.style.height = '380px';
chart.canvas.parentNode.style.width = '700px';
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.bundle.min.js"></script>
<canvas id="myChart"></canvas>