JSFiddle - React, Tailwind, and code Playground

by schrodingers

HTML

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

CSS

body {
  background: #000;
}

JavaScript

/* Metaballs js canvas */
var canvas = document.getElementById("canvas"),
  ctx = canvas.getContext("2d"),
  tempCanvas = document.createElement("canvas"),
  tempCtx = tempCanvas.getContext("2d"),
  width = 800,
  height = 600,
  
  threshold = 210,
  colors = {
    r: 255,
    g: 0,
    b: 0
  },
  cycle = 0,
  points = [];

canvas.width = tempCanvas.width = width;
canvas.height = tempCanvas.height = height;

for (var i = 0; i < 50; i++) {
  var x = Math.random() * width,
    y = Math.random() * height,
    vx = (Math.random() * 8) - 4,
    vy = (Math.random() * 8) - 4,
    size = Math.floor(Math.random() * 60) + 60;

  points.push({
    x: x,
    y: y,
    vx: vx,
    vy: vy,
    size: size
  });

};

function update() {
  var len = points.length;
  tempCtx.clearRect(0, 0, width, height);
  while (len--) {
    var point = points[len];
    point.x += point.vx;
    point.y += point.vy;

    if (point.x > width + point.size) {
      point.x = 0 - point.size;
    }
    if (point.x < 0 - point.size) {
      point.x = width + point.size;
    }
    if (point.y > height + point.size) {
      point.y = 0 - point.size;
    }
    if (point.y < 0 - point.size) {
      point.y = height + point.size;
    }

    tempCtx.beginPath();
    var grad = tempCtx.createRadialGradient(point.x, point.y, 1, point.x, point.y, point.size);
    grad.addColorStop(0, 'rgba(' + colors.r + ',' + colors.g + ',' + colors.b + ',1)');
    grad.addColorStop(1, 'rgba(' + colors.r + ',' + colors.g + ',' + colors.b + ',0)');
    tempCtx.fillStyle = grad;
    tempCtx.arc(point.x, point.y, point.size, 0, Math.PI * 2);
    tempCtx.fill();
  }
  metabalize();
  colorCycle();
  setTimeout(update, 10);
}

function colorCycle() {
  cycle += 0.1;
  if (cycle > 100) {
    cycle = 0;
  }
  colors.r = ~~(Math.sin(.3 * cycle + 0) * 127 + 128);
  colors.g = ~~(Math.sin(.3 * cycle + 2) * 127 + 128);
  colors.b = ~~(Math.sin(.3 * cycle + 4) * 127 + 128);
}

function metabalize() {
  var imageData =...