JSFiddle - React, Tailwind, and code Playground
by Josh Pullen
CSS
canvas {
border: 1px solid black;
width: 100%;
}
JavaScript
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
canvas.width = 1280;
canvas.height = 720;
const lerp = (a, b, t = 0) => {
if (Array.isArray(a) && Array.isArray(b)) {
let result = [];
for (let i = 0; i < a.length; i++) {
result.push(lerp(a[i], b[i], t));
}
return result;
}
if (t < 0) t = 0;
if (t > 1) t = 1;
return a + (b - a) * t;
}
const ease = {
sin: (t) => (1 - Math.cos(t * Math.PI)) / 2,
out: (t) => 1 - (1 - t) ** 3,
}
function grid([minX, maxX], [minY, maxY], [sizeX, sizeY], [cx, cy]) {
ctx.strokeStyle = "#ddd";
ctx.lineWidth = 4;
ctx.lineCap = "square";
for (let x = minX; x <= maxX; x++) {
ctx.beginPath();
ctx.moveTo(cx + sizeX * x, cy + sizeY * minY);
ctx.lineTo(cx + sizeX * x, cy + sizeY * maxY);
ctx.stroke();
}
for (let y = minY; y <= maxY; y++) {
ctx.beginPath();
ctx.moveTo(cx + sizeX * minX, cy + sizeY * y);
ctx.lineTo(cx + sizeX * maxX, cy + sizeY * y);
ctx.stroke();
}
ctx.strokeStyle = "#aaa";
ctx.lineWidth = 6;
ctx.beginPath();
ctx.moveTo(cx + sizeX * 0, cy + sizeY * minY + 1);
ctx.lineTo(cx + sizeX * 0, cy + sizeY * maxY - 1);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(cx + sizeX * minX + 1, cy + sizeY * 0);
ctx.lineTo(cx + sizeX * maxX - 1, cy + sizeY * 0);
ctx.stroke();
}
function render(t) {
ctx.fillStyle = "white";
ctx.fillRect(0, 0, canvas.width, canvas.height);
grid(
[-4, 4],
[-3, 3],
lerp(
[75, 75],
[150, 75],
ease.sin(lerp(0, 1, Math.min(t - 10, 14.25 - t)))
),
[640, 400]
);
/*
arrow(
lerp(0, 1, Math.max(Math.min(t - 4, 8 - t), t - 10)),
lerp(0, 1, t - 13.25),
lerp(0, 1, 2 * (t - 12))
);
*/
circle(
lerp(0, 1, t - 0.5),
lerp(0, 1, Math.min(t - 4, 8 - t)),
lerp(0, 1, Math.min(3 * (t - 9), 3 * (11.5 - t))),
lerp(0, 1, 1.3 * (t - 6)),
lerp(0, 1, t - 13.25)
);
face(lerp(0,...