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], gridSize, [cx, cy]) {
	ctx.strokeStyle = "#ddd";
  ctx.lineWidth = 4;
  ctx.lineCap = "square";

	for (let x = -5; x <= 5; x++) {
    ctx.beginPath();
    ctx.moveTo(cx + gridSize * x, cy + gridSize * -4);
    ctx.lineTo(cx + gridSize * x, cy + gridSize * 4);
    ctx.stroke();
  }

  for (let y = -4; y <= 4; y++) {
    ctx.beginPath();
    ctx.moveTo(cx + gridSize * -5, cy + gridSize * y);
    ctx.lineTo(cx + gridSize * 5, cy + gridSize * y);
    ctx.stroke();
  }

  ctx.strokeStyle = "#aaa";
  ctx.lineWidth = 6;

  ctx.beginPath();
  ctx.moveTo(cx + gridSize * 0, cy + gridSize * -4 + 1);
  ctx.lineTo(cx + gridSize * 0, cy + gridSize * 4 - 1);
  ctx.stroke();

  ctx.beginPath();
  ctx.moveTo(cx + gridSize * -5 + 1, cy + gridSize * 0);
  ctx.lineTo(cx + gridSize * 5 - 1, cy + gridSize * 0);
  ctx.stroke();
}

function render(t) {
	ctx.fillStyle = "white";
	ctx.fillRect(0, 0, canvas.width, canvas.height);

  grid(
  	[-5, 5],
    [-4, 4],
    60,
    lerp(
    	[640, 400],
      [640 + 180, 400 - 180],
      ease.sin(lerp(0, 1, Math.min(t - 10, 14.25 - t)))
    )
  );
  
  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)
  );
  
 ...