JSFiddle - React, Tailwind, and code Playground

by Scott Kaye

HTML

<canvas id="c"></canvas>

JavaScript

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

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

class Point {
  constructor(pin = false) {
    let x = Math.random() * 40 + 50;
    let y = Math.random() * 40 + 50;
  
    this.x = x;
    this.y = y;
    this.pin = pin;
    this.vx = 0;
    this.vy = 0;
  }
}

let numPoints = 10;
let points = [new Point(true)];
for(let p=0;p<numPoints;++p)points.push(new Point());

function smoothThrough(points) {
  ctx.beginPath();
  ctx.moveTo(points[0].x, points[0].y);
  let i;
  for (i = 1; i < points.length - 2; ++i) {
    var xc = (points[i].x + points[i + 1].x) / 2;
    var yc = (points[i].y + points[i + 1].y) / 2;
    ctx.quadraticCurveTo(points[i].x, points[i].y, xc, yc);
  }
  ctx.quadraticCurveTo(points[i].x, points[i].y, points[i + 1].x, points[i + 1].y);
}

function clamp(i, min, max) {
	return i >= min && i <= max ? i : i < min ? min : max;
}

function update() {
  ctx.fillStyle = "#fff";
  ctx.fillRect(0, 0, canvas.width, canvas.height);

  for (let i = 0; i < points.length; ++i) {
    // Debug:
    ctx.fillStyle = "#f00";
    ctx.fillRect(points[i].x - 2, points[i].y - 2, 4, 4);

    if (points[i - 1]) {
      let diffX = points[i - 1].x - points[i].x;
      let diffY = points[i - 1].y - points[i].y;
      let d = Math.sqrt(diffX * diffX + diffY * diffY);
      let diff = ((numPoints / canvas.width) - d) / d;
      let tX = diffX * 0.35 * diff;
      let tY = diffY * 0.35 * diff;

      if (!points[i].pin) {
        points[i].vx -= tX;
        points[i].vy -= tY;
      }

      if (!points[i - 1].pin) {
        points[i - 1].vx += tX;
        points[i - 1].vy += tY;
      }
    }

    if (!points[i].pin) {
      // Inertia
      points[i].vx = clamp(points[i].vx, -15, 15);
      points[i].vy = clamp(points[i].vy, -15, 15);
      points[i].x += points[i].vx;
      points[i].y += points[i].vy;
      
      points[i].vx *= 0.85;
      points[i].vy *= 0.85;
    ...