community!
I am working on a project using HTML5 Canvas and JavaScript/jQuery, where I have multiple animated routes between points on a grid. The animation should smoothly draw lines from point A to point B, but I’m having trouble achieving a smoother movement for the line.
Here’s the code I’m using:
$(document).ready(function () {
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const points = [];
const routes = [];
const pointRadius = 10;
const gridSize = 60; // Spacing between points
const numRows = Math.floor(canvas.width / gridSize);
const numCols = Math.floor(canvas.height / gridSize);
const animationDuration = 2000; // Total animation time (adjustable)
// Function to draw a point
function drawPoint(x, y, color = 'black') {
ctx.beginPath();
ctx.arc(x, y, pointRadius, 0, 2 * Math.PI);
ctx.fillStyle = color;
ctx.fill();
ctx.strokeStyle = color;
ctx.stroke();
}
// Function to draw the full curve from A to B
function drawFullCurve(pointA, pointB, colorStart, colorEnd) {
const midX = (pointA.x + pointB.x) / 2;
const midY = (pointA.y + pointB.y) / 2 - 50; // Curve elevation
const gradient = ctx.createLinearGradient(pointA.x, pointA.y, pointB.x, pointB.y);
gradient.addColorStop(0, colorStart);
gradient.addColorStop(1, colorEnd);
ctx.beginPath();
ctx.moveTo(pointA.x, pointA.y);
ctx.quadraticCurveTo(midX, midY, pointB.x, pointB.y);
ctx.strokeStyle = gradient;
ctx.lineWidth = 2;
ctx.stroke();
}
// Function to animate the reveal of the curve from A to B
function animateCurve(pointA, pointB, colorStart, colorEnd, duration) {
let startTime = performance.now();
function animateStep(timestamp) {
const elapsedTime = timestamp - startTime;
const progress = Math.min(elapsedTime / duration, 1); // Progress from 0 to 1
// Do not clear the entire canvas! Keep previous routes
ctx.save();
ctx.beginPath();
ctx.moveTo(pointA.x, pointA.y);
// Calculate intermediate position using linear interpolation
const t = progress;
const midX = (pointA.x + pointB.x) / 2;
const midY = (pointA.y + pointB.y) / 2 - 50;
const revealX = (1 - t) * ((1 - t) * pointA.x + t * midX) + t * ((1 - t) * midX + t * pointB.x);
const revealY = (1 - t) * ((1 - t) * pointA.y + t * midY) + t * ((1 - t) * midY + t * pointB.y);
ctx.quadraticCurveTo(midX, midY, revealX, revealY);
ctx.clip();
drawFullCurve(pointA, pointB, colorStart, colorEnd);
ctx.restore();
drawPoint(pointA.x, pointA.y, colorStart);
drawPoint(pointB.x, pointB.y, colorEnd);
if (progress < 1) {
requestAnimationFrame(animateStep);
}
}
requestAnimationFrame(animateStep);
}
// Generate points
for (let i = 0; i < numRows; i++) {
for (let j = 0; j < numCols; j++) {
const x = i * gridSize + gridSize / 2;
const y = j * gridSize + gridSize / 2;
points.push({ x, y });
drawPoint(x, y);
}
}
// Generate 20 random routes
function generateRandomRoutes() {
for (let i = 0; i < 20; i++) {
const startPoint = points[Math.floor(Math.random() * points.length)];
const endPoint = points[Math.floor(Math.random() * points.length)];
routes.push({ startPoint, endPoint });
}
}
generateRandomRoutes();
// Function to animate routes simultaneously
function animateRoutes() {
routes.forEach(route => {
const colorStart = 'blue';
const colorEnd = 'red';
const { startPoint, endPoint } = route;
// Execute the animation for each route without clearing the canvas
animateCurve(startPoint, endPoint, colorStart, colorEnd, animationDuration);
});
}
// Execute the animation of the routes
animateRoutes();
});
Problem:
The animation is not as smooth as I would like. Instead, the line seems to be “drawn” abruptly from A to B. What I want is for the line to be drawn smoothly, as if it’s being traced over time, instead of appearing all at once.
Question:
How can I smooth out this animation so that the line appears more fluid? Any tips on improving the interpolation calculation or how the line is drawn would be greatly appreciated!
Thank you in advance for your help!