Reputation: 175
I have a graph that displays data of the last 2h, 8h, 24h, or 48h. This can be changed via buttons on the webpage. When the timespan includes midnight, I would like to display vertical lines with little labels (maybe at hover) at midnight displaying the date (or day of the week) of the upcoming day.
I have not found any resources on how to do that in Chartjs 3. How would I do such a task?
This is how I create the graph. "time" is an array of epoch times:
chart = new Chart(
document.getElementById('Chart'),
{
type: 'line',
data:
{
labels: time,
datasets: [
{
label: dataObjects[start].label,
backgroundColor: dataObjects[start].backgroundColor,
borderColor: dataObjects[start].borderColor,
fill: dataObjects[start].fill,
data: dataObjects[start].data,
yAxisID: 'A',
}]
},
options: {
elements: {point: {radius: 0.5, borderWidth: 1},
line: {borderWidth: 3}},
maintainAspectRatio: false,
scales: {
x:
{
//max: last_time,
type: "time",
grid: {borderColor: color.time},
ticks: {color: color.time},
time: {
unit: 'hour',
tooltipFormat: 'dd.MM. HH:mm',
displayFormats: {
second: "HH:mm",
minute: "HH:mm",
hour: "HH:mm",
day: "d.MM.",
week: "d.MM."
},
}
},
A:
{
type: 'linear',
grid: {borderColor: color.time},
position: 'left',
ticks: {color: color.time},
suggestedMin: dataObjects[start].suggestedMin,
suggestedMax: dataObjects[start].suggestedMax,
title: {text: dataObjects[start].text,
display: true,
color: color.time}
}
},
plugins: {
legend: {display: false}
}
}
});
Upvotes: 3
Views: 3883
Reputation: 89
This is my solution, it uses Luxon to split a range of dates into an interval of days, changes each of those DateTime instances to midnight, then gets a timestamp value from them.
The for loop builds a dictionary of line annotations from the array of timestamps, and assigns that to the ChartJS annotation plugin.
edit: I'm calling this function in created()
to update on redraws
drawAnnotations() {
let annotations = {};
let arr = this.chartData.datasets[0].data;
let startDate = DateTime.fromISO(arr[0].x);
let endDate = DateTime.fromISO(arr[arr.length - 1].x);
let intervals = Interval.fromDateTimes(
startDate.startOf("day"),
endDate.endOf("day")
)
.splitBy({ day: 1 })
.map((date) => date.start.set({ hour: 0 }).valueOf());
for (let d of intervals) {
annotations[d] = {
type: "line",
xMin: d,
xMax: d,
borderColor: "rgb(255, 99, 132)",
borderWidth: 2,
};
}
this.chartOptions.plugins.annotation.annotations = annotations;
},
Upvotes: 0
Reputation: 31371
You could use the annotation plugin. In your case you will need to change the string I used to determine the correct x axis placement to the timestamp of the midnight you want and then you have a line there:
const options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderColor: 'pink'
}]
},
options: {
plugins: {
annotation: {
annotations: {
line1: {
type: 'line',
xMin: 'Green',
xMax: 'Green',
label: {
enabled: true,
content: 'end value'
}
},
line2: {
type: 'line',
xMin: 'Blue',
xMax: 'Blue',
label: {
enabled: true,
content: 'begin value'
}
}
}
}
}
}
}
const ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-annotation/1.3.1/chartjs-plugin-annotation.min.js"></script>
</body>
Upvotes: 2
Reputation: 151
You can use a mixed chart to create this graph mixing a line chart and a bar chart.
Here you can view one example:
https://codepen.io/alyf-mendonca/pen/dyZZoeB
HTML:
<div>
<canvas id="myChart"></canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
JS:
const labels = [
'January',
'February',
'March',
'April',
'May',
'June',
];
const data = {
labels: [
'20:00',
'21:00',
'22:00',
'23:00',
'00:00',
'01:00',
'02:00'
],
datasets: [{
type: 'line',
label: 'Bar Dataset',
data: [20, 21, 23, 22, 21, 20, 23],
borderColor: 'rgb(255, 99, 132)',
backgroundColor: 'rgba(255, 99, 132, 0.2)'
}, {
type: 'bar',
label: 'Line Dataset',
data: [0, 0, 0, 0, 50, 0, 0],
fill: false,
borderColor: 'rgb(54, 162, 235)'
}]
};
const config = {
type: 'bar',
data: data,
options: {
scales: {
x: {
stacked: true
}
}
},
};
const myChart = new Chart(
document.getElementById('myChart'),
config
);
Upvotes: 1