I'm trying to get my graph line to animate like progressive line chart https://www.chartjs.org/docs/latest/samples/animations/progressive-line.html
I'm only able to get get default animation.
Here is my code
<script>
// Define the data for the chart
const data1 = [
{ x: "25", y: 65 },
{ x: "40", y: 60 },
{ x: "60", y: 30 },
{ x: ">70", y: 12 }
];
const data2 = [
{ x: "25", y: 65 },
{ x: "40", y: 60 },
{ x: "60", y: 35 },
{ x: ">70", y: 45 }
];
// Create labels and values arrays from the data
const labels = data1.map(point => "Age " + point.x);
// Get the canvas context
const ctx = document.getElementById('myChart').getContext('2d');
// Create a new Chart instance with the first dataset (data1)
const myChart = new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: [
{
label: 'NAD+ Level',
data: data1.map(point => point.y),
borderColor: 'white',
borderWidth: 2,
backgroundColor: 'rgba(0, 0, 0, 0)',
lineTension: 0.4,
pointBackgroundColor: 'white',
pointBorderColor: 'white',
pointBorderWidth: 1
}
]
},
options: {
animation: {
duration: 5000, // Set the animation duration for data1
easing: 'linear'
},
responsive: true,
maintainAspectRatio: false,
scales: {
x: {
ticks: {
color: 'white',
},
grid: {
color: (context) => (context.tick.value === 0) ? 'white' : 'transparent',
display: true,
drawTicks: false
}
},
y: {
beginAtZero: true,
ticks: {
color: 'white',
},
grid: {
color: (context) => (context.tick.value === 0) ? 'white' : 'transparent',
display: true
}
}
},
plugins: {
legend: {
display: true,
position: 'bottom',
align: 'end',
labels: {
color: 'white'
}
}
},
elements: {
point: {
radius: 0,
backgroundColor: 'white',
borderColor: 'white',
borderWidth: 1
}
}
}
});
// Function to check if the mouse hovers over the chart
function isMouseOverChart(event) {
const canvas = document.getElementById('myChart');
const rect = canvas.getBoundingClientRect();
const mouseX = event.clientX - rect.left;
const mouseY = event.clientY - rect.top;
return mouseX >= 0 && mouseX <= canvas.width && mouseY >= 0 && mouseY <= canvas.height;
}
// Function to render the second dataset (data2) when the mouse hovers over the chart
function renderSecondDataset(event) {
if (isMouseOverChart(event)) {
if (myChart.data.datasets.length === 1) {
myChart.data.datasets.push({
label: 'NAD+ Level (After Blue Helix)',
data: data2.map(point => point.y),
borderColor: '#B4FFBB',
borderWidth: 2,
backgroundColor: 'rgba(0, 0, 0, 0)',
lineTension: 0.4,
pointBackgroundColor: 'white',
pointBorderColor: 'white',
pointBorderWidth: 1
});
myChart.options.animation.duration = 1500; // Set the animation duration for data2
myChart.update();
}
}
}
// Function to remove data2 when the mouse leaves the chart
function removeData2() {
if (!isMouseOverChart(event) && myChart.data.datasets.length > 1) {
myChart.data.datasets.pop(); // Remove the last dataset (data2)
myChart.options.animation.duration = 1500; // Restore the animation duration for data1
myChart.update();
}
}
// Add a mousemove listener to trigger the rendering of the second dataset (data2)
const canvas = document.getElementById('myChart');
canvas.addEventListener('mousemove', renderSecondDataset);
// Add a mouseleave listener to remove data2 when the mouse leaves the chart
canvas.addEventListener('mouseleave', removeData2);
// Resize chart when window is resized
window.addEventListener('resize', () => {
myChart.resize();
});
</script>
I try to create random points for both data sets to hit and start drawing the line from there but It doesn't seem to work
const data = [
{ x: "25", y: 65 },
{ x: "40", y: 60 },
{ x: "60", y: 30 },
{ x: ">70", y: 12 }
];
const data2 = [
{ x: "25", y: 65 },
{ x: "40", y: 60 },
{ x: "60", y: 35 },
{ x: ">70", y: 45 }
];
const randomData = [];
const randomData2 = [];
// Function to generate a random y value that doesn't exceed the next value
function generateRandomY(prevY, nextY) {
if (nextY === undefined) {
return prevY;
}
const randomY = prevY + Math.random() * (nextY - prevY);
return randomY > nextY ? nextY : randomY;
}
// Generate random points for data
data.forEach((currentPoint, i) => {
// Initialize with the predefined points
randomData.push(currentPoint);
// Generate more random points between current and next predefined points
while (randomData.length < (i + 2) * 10) { // You can adjust the factor to generate more points
const prevY = randomData[randomData.length - 1].y;
const nextY = data[i + 1] ? data[i + 1].y : undefined;
const randomY = generateRandomY(prevY, nextY);
const x = (parseFloat(currentPoint.x) + (randomData.length - i - 1) / 10).toString();
randomData.push({ x, y: randomY });
}
});
// Generate random points for data2
data2.forEach((currentPoint, i) => {
// Initialize with the predefined points
randomData2.push(currentPoint);
// Generate more random points between current and next predefined points
while (randomData2.length < (i + 2) * 10) { // You can adjust the factor to generate more points
const prevY = randomData2[randomData2.length - 1].y;
const nextY = data2[i + 1] ? data2[i + 1].y : undefined;
const randomY = generateRandomY(prevY, nextY);
const x = (parseFloat(currentPoint.x) + (randomData2.length - i - 1) / 10).toString();
randomData2.push({ x, y: randomY });
}
});
// Define the animation options
const totalDuration = 10000;
const delayBetweenPoints = totalDuration / (randomData.length - 1);
const previousY = (ctx) => ctx.index === 0 ? ctx.chart.scales.y.getPixelForValue(100) : ctx.chart.getDatasetMeta(ctx.datasetIndex).data[ctx.index - 1].getProps(['y'], true).y;
const animation = {
x: {
type: 'number',
easing: 'linear',
duration: delayBetweenPoints,
from: NaN, // the point is initially skipped
delay(ctx) {
if (ctx.type !== 'data' || ctx.xStarted) {
return 0;
}
ctx.xStarted = true;
return ctx.index * delayBetweenPoints;
}
},
y: {
type: 'number',
easing: 'linear',
duration: delayBetweenPoints,
from: previousY,
delay(ctx) {
if (ctx.type !== 'data' || ctx.yStarted) {
return 0;
}
ctx.yStarted = true;
return ctx.index * delayBetweenPoints;
}
}
};
// Create the chart configuration
const config = {
type: 'line',
data: {
datasets: [{
borderColor: Utils.CHART_COLORS.red,
borderWidth: 1,
radius: 0,
data: randomData, // Use the generated random data
},
{
borderColor: Utils.CHART_COLORS.blue,
borderWidth: 1,
radius: 0,
data: randomData2, // Use the generated random data for data2
}]
},
options: {
animation,
interaction: {
intersect: false
},
plugins: {
legend: false
},
scales: {
x: {
type: 'linear'
}
}
}
};
// Create the chart using Chart.js
const ctx = document.getElementById('myChart').getContext('2d');
const myChart = new Chart(ctx, config);