HTML Canvas line animation
Ming Sun / May 08, 2023
4 min read • ––– views
React component
The following code will create a boiler template for HTML canvas.
import { useEffect } from "react";
const mouse = { x: 0, y: 0 };
class FlowFieldEffect {
#ctx;
#width;
#height;
constructor(ctx, width, height) {
this.#ctx = ctx;
this.#ctx.lineWidth = 0.5;
this.#width = width;
this.#height = height;
this.#ctx.strokeStyle = "white";
this.lastTime = 0;
this.interval = 1000 / 120;
this.timer = 0;
this.cellSize = 12;
this.gradient;
this.createGradient();
this.#ctx.strokeStyle = this.gradient;
this.radius = 0;
this.vr = 0.01;
}
createGradient() {
this.gradient = this.#ctx.createLinearGradient(
0,
0,
this.#width,
this.#height
);
this.gradient.addColorStop("0.1", "#ff5c33");
this.gradient.addColorStop("0.2", "#ff66b3");
this.gradient.addColorStop("0.3", "#ccccff");
this.gradient.addColorStop("0.4", "#b3ffff");
this.gradient.addColorStop("0.8", "#80ff80");
this.gradient.addColorStop("0.9", "#ffff33");
}
drawLine(angle, x, y) {
let positionX = x;
let positionY = y;
let dx = mouse.x - positionX;
let dy = mouse.y - positionY;
const length = 30;
this.#ctx.beginPath();
this.#ctx.moveTo(x, y);
this.#ctx.lineTo(
x + Math.cos(angle) * length,
y + Math.sin(angle) * length
);
this.#ctx.stroke();
}
animate(timeStamp) {
const deltaTime = timeStamp - this.lastTime;
this.lastTime = timeStamp;
this.radius += this.vr;
if (this.radius > 10 || this.radius < -10) {
this.vr *= -1;
}
if (this.timer > this.interval) {
this.#ctx.clearRect(0, 0, this.#width, this.#height);
for (let y = 0; y < this.#height; y += this.cellSize) {
for (let x = 0; x < this.#width; x += this.cellSize) {
const angle = this.radius * (Math.cos(x * 0.01) + Math.sin(y * 0.01));
this.drawLine(angle, x, y);
}
}
this.timer = 0;
} else {
this.timer += deltaTime;
}
requestAnimationFrame(this.animate.bind(this));
}
}
const CanvasLineAnimation = () => {
useEffect(() => {
const canvasParent = document.getElementById("canvasParent");
const canvas = document.getElementById("canvas1");
canvas.style.background = "black";
const ctx = canvas.getContext("2d");
canvas.width = canvasParent.offsetWidth;
canvas.height = 800;
const flowField = new FlowFieldEffect(ctx, canvas.width, canvas.height);
flowField.animate(0);
canvas.addEventListener("mousemove", function (e) {
mouse.x = e.offsetX;
mouse.y = e.offsetY;
});
}, []);
return (
<div id="canvasParent" className="w-full">
<canvas id="canvas1"></canvas>
</div>
);
};
export default CanvasLineAnimation;