I need to plot series with vertical edges. But it seems duplicate x
may confuse chart.js so it does not render correct plot.
My current approach is slightly modify the x
to make them different. However, I’m not very satisfy with the 11.999999
in my code. So i believe there should be some better way to express the vertical edge. And i want to know what is the correct way to plot it.
const TASKS = [
{ start: 6.5, end: 23.5, value: 17 },
{ start: 0, end: 12, value: 8 },
{ start: 12, end: 23.5, value: 23 },
{ start: 0, end: 6.5, value: 1 },
{ start: 23.5, end: 24, value: 6 },
];
const COLORS = ["#80dfff80", "#ff80df80", "#dfff8080", "#e5d29980", "#99e5d280"];
function formatTasks(tasks, epsilon) {
const xValues = [...new Set(tasks.flatMap(task => [task.start, task.end, Math.max(0, task.start - epsilon), task.end - epsilon]))].sort((a, b) => a - b);
const result = tasks.map(task => xValues.map(x => ({
x,
y: x >= task.start && x < task.end ? task.value : 0
})));
console.log(result);
return result;
}
; [0, 1e-6].forEach((EPSILON, chartIndex) => {
new Chart('chart' + (chartIndex + 1), {
"type": "scatter",
"data": {
"labels": [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23" ],
"datasets": formatTasks(TASKS, EPSILON).map((data, index) => ({
"type": "scatter",
"label": "Task " + (index + 1),
"yAxisID": "y",
"showLine": true,
"pointRadius": 0,
"pointHoverRadius": 0,
"borderWidth": 0,
"borderColor": "transparent",
"pointStyle": "rect",
"backgroundColor": COLORS[index],
"stack": "tasks",
"fill": index ? "-1" : "origin",
"data": data,
})),
},
"options": {
"responsive": true,
"maintainAspectRatio": false,
"animation": false,
"plugins": {
"legend": {
"position": "bottom",
"labels": {
"usePointStyle": true
}
},
},
"scales": {
"x": {
"min": 0,
"max": 24,
"ticks": {
"minRotation": 0,
"maxRotation": 0,
"stepSize": 1
}
},
"y": {
"type": "linear",
"position": "left",
"beginAtZero": true,
"stacked": true,
"ticks": {
"format": {
"maximumFractionDigits": 0
}
}
},
}
}
})
});
.chart-container { position: relative; margin: auto; height: 40vh; width: 80vw; min-height: 200px; }
Chart 1: (Epsilon = 0) This does not work
<div class="chart-container"><canvas id="chart1"></canvas></div>
Chart 2: (Epsilon = 1e-6) This works, but a bit ugly
<div class="chart-container"><canvas id="chart2"></canvas></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.min.js"></script>