JSFiddle - React, Tailwind, and code Playground

by Paolo Salvagione

HTML

<canvas width="800" height="800"></canvas>

CSS

canvas {
    border: 1px solid #ccc;
}

JavaScript

var canvas = document.querySelector("canvas"),
    context = canvas.getContext("2d"),
    width = canvas.width,
    height = canvas.height,
    count = 10,
    sizeMin = 0,
    sizeMax = 100,
    xMin = 0,
    xMax = width / 2,
    thetaMin = 0,
    thetaMax = 12.28362727553609,
    angle = 0,
    speed = 1.05;

context.globalAlpha = .2;

setInterval(draw, 50);

canvas.addEventListener("mousedown", function(e) {
  canvas.addEventListener("mousemove", move);
  document.addEventListener("mouseup", function() {
    canvas.removeEventListener("mousemove", move);
  });
});

canvas.addEventListener("touchstart", function(e) {
  canvas.addEventListener("touchmove", move);
  document.addEventListener("touchend", function() {
    canvas.removeEventListener("touchmove", move);
  });
});


function move(e) {
  if (e.type === "touchmove") {
    // figure out what x and y are here
  }
  thetaMax = scale(e.offsetX, 0, canvas.width, Math.PI / 2, Math.PI * 16);
  count = scale(e.offsetY, 0, canvas.height, 50, 500);
}

function draw() {
  context.clearRect(0, 0, width, height);
  for (var i = 0; i < count; i++) {
    context.save();

    var radius = scale(i, 0, count - 1, sizeMin, sizeMax),
        theta = scale(i, 0, count - 1, thetaMin, thetaMax),
        x = scale(i, 0, count - 1, xMin, xMax);
    context.beginPath();

    context.translate(width / 2, height / 2);
    context.rotate(angle + theta);
    context.translate(x, 0);
    context.arc(0, 0, radius, 0, Math.PI * 2);

    context.closePath();
    context.stroke();

    context.restore();
  }
  // if (sizeMax > 1000) {
  //   speed = .98;
  //   sizeMax = 1000;
  // } else if (sizeMax < 50) {
  //   speed = 1.01;
  //   sizeMax = 50;
  // } else {
  //   sizeMax *= speed;
  // }
  angle += .01;
}

function scale(n, inMin, inMax, outMin, outMax) {
  return outMin + (outMax - outMin) * (n - inMin) / (inMax - inMin);
}