JSFiddle - React, Tailwind, and code Playground

by Josh Pullen

CSS

canvas {
  border: 1px solid black;
}

JavaScript

const points = [
	[200, 200],
  /* [200, 200], */
  [300, 250],
  [200, 400]
];

const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");

document.body.appendChild(canvas);

canvas.width = 500;
canvas.height = 500;

for (const point of points) {
	ctx.beginPath();
  ctx.arc(point[0], point[1], 5, 0, 2 * Math.PI);
  ctx.fill();
}

function bezier(points, t) {
	let newPoints = [];
  for (let i = 0; i < points.length - 1; i++) {
  	newPoints.push([
    	points[i][0] + t * (points[i+1][0] - points[i][0]),
      points[i][1] + t * (points[i+1][1] - points[i][1]),
    ]);
  }
  
  if (newPoints.length === 1) {
    return newPoints[0];
  }
  
  return bezier(newPoints, t);
}

ctx.beginPath();
ctx.moveTo(...bezier(points, -1));
for (let t = -1; t <= 2; t += 0.01) {
	ctx.lineTo(...bezier(points, t));
}
ctx.stroke();