JSFiddle - React, Tailwind, and code Playground

by soulwire

CSS

html,
body {
  margin: 0;
  background: #222;
}

JavaScript

const MAX = 24;

const canvas = document.createElement('canvas');
canvas.width = innerWidth;
canvas.height = innerHeight;
document.body.appendChild(canvas);

const ctx = canvas.getContext('2d');

let camera = {
	x: 0,
  y: 0,
  s: 1
}

let vines = [{
  x: 0,
  y: 0,
  a: 0, // angle
  ai: 0, // angle step
  w: 8, // speed
  p: [],
  l: MAX * 60 // length
}]

let frame = 0;
const tick = () => {
  requestAnimationFrame(tick);
  vines = vines.filter(v => v.l--);
  vines.forEach(v => {
    dx = Math.cos(v.a) * v.w / 2;
    dy = Math.sin(v.a) * v.w / 2;
    v.x += dx;
    v.y += dy;
    v.a += v.ai / v.w / 2;
    v.p.splice(0, v.p.length - v.l);
    v.p.splice(0, v.p.length - 60 * 5);
    v.p.push({
      x: v.x,
      y: v.y,
      dx: dx,
      dy: dy
    });
    if (frame % 30 == 0) {
      v.ai = Math.random() - .5;
    }
    if (v.w > 1 && Math.random() < v.l / 16384 / 3) {
      vines.push({
        x: v.x,
        y: v.y,
        a: v.a,
        ai: v.ai,
        w: v.w / 2,
        p: [],
        l: Math.min(v.l, 0 | v.w * 32 * (1 + Math.random()))
      });
    }
  })

  H = canvas.height = innerHeight;
  W = canvas.width = innerWidth;
  let head = vines[0].p[0];
  camera.x += (head.x - camera.x) * 0.1;
  camera.y += (head.y - camera.y) * 0.1;
  camera.s = 1 + Math.abs(Math.sin(frame * 0.01)) * 2;
  ctx.translate(W / 2, H / 2);
  //ctx.translate(camera.x, camera.y);
  //ctx.scale(camera.s, camera.s);
  
  //ctx.translate(W / 2, H / 2);
  //ctx.shadowBlur = 24;
  vines.forEach(v => {
    ctx.shadowColor =
      ctx.strokeStyle = 'hsl(' + (v.a * 60 | 0) + ',100%,' + (60 + v.w * 5) + '%)';
    if (v.w == 8) {
      ctx.rotate(v.a);
      //ctx.drawImage(img,frame*4&112,0,16,24,-8,0,-16,-24)
      ctx.rotate(-v.a);
      ctx.translate(-v.x, -v.y);
    }
    ctx.beginPath();
    l = v.p.length - 1;
    for (i = l; p = v.p[i]; i--) {
    	if (i === l) {
      	ctx.moveTo(p.x, p.y);
      } else {
      	ctx.lineTo(p.x, p.y);
      }
    }
    /*
    l = v.p.length...