Intro to bezier curve: draw bezier curve animation

by johnsonjo4531

HTML

<canvas width="1000px" height="1000px" id="canvas" style="width: 100vw; height: 100vh;"/>

CSS

html, body {
margin: 0;
padding: 0;
max-height: 100vh;
max-width: 100vw;
overflow: hidden;
}

TypeScript

/** lerp two scalars/numbers
 * @param v0 the number to start the lerp from
 * @param v1 the number to lerp towards
 * @param t the percentage of the lerp
 */
function lerp(v0: number, v1: number, t: number) {
  return v0 + t * (v1 - v0);
}

/** A 2D vector representing a point in 2D space among other things... */
class Vector2 {
  x=0;
  y=0;

  constructor (x: number, y: number) {
    this.x = x;
    this.y = y;
  }

  /** lerp two vec2s
   * @param vec2 another vec2 to lerp towards
   * @param t the percentage of the current lerp
   */
  lerp (vec2: Vector2, t: number) {
    return new Vector2(lerp(this.x, vec2.x, t), lerp(this.y, vec2.y, t));
  }
}

function quadratic_bezier(p0: Vector2, p1: Vector2, p2: Vector2, t: number) {
	var q0 = p0.lerp(p1, t);
	var q1 = p1.lerp(p2, t);

  var r = q0.lerp(q1, t);
  return r;
}

let canvas = document.getElementById("canvas");

if (!(canvas instanceof HTMLCanvasElement)) {
  throw new Error("#canvas must be a canvas element.");
}

let p0 = new Vector2(250, 750);
let p1 = new Vector2(450, 500);
let p2 = new Vector2(750, 750);

canvas.addEventListener("click", (e) => {
  p1 = new Vector2(lerp(0, 1000, e.clientX/document.body.clientWidth), lerp(0, 1000, e.clientY/document.body.clientHeight));
});

let ctx = canvas.getContext("2d");

let maxTimeSteps = 100;
setInterval(() => {
  // clear everything each animation frame
  ctx.clearRect(0,0,1000,1000);
  // DRAW POINTS
  const radius = 10;
  const points = [p0,p1,p2];
  ctx.beginPath();
  for(const p of points) {
    ctx.moveTo(p.x, p.y);
    ctx.fillStyle = "black";
    ctx.ellipse(p.x, p.y, radius, radius, 0, 0, 2 * Math.PI);
    ctx.fill();
  }
  ctx.closePath();

  /// Draw lines between points
  ctx.beginPath();
  for (let i = 0; i < points.length - 1; ++i) {
    const p0 = points[i];
    const p1 = points[i + 1];
    ctx.strokeStyle = "grey";
    ctx.moveTo(p0.x, p0.y);
    ctx.lineTo(p1.x,...