JSFiddle - React, Tailwind, and code Playground

by MegaScience

HTML

<canvas></canvas>
<button>Clear</button>

CSS

html,
body {
  background: #777;
  margin: 0;
  overflow: hidden
}

canvas {
  position: fixed;
  left: 0;
  top: 0;
  background: #333
}

button {
  position: fixed;
  left: 10px;
  top: 10px
}

JavaScript

// From: http://stackoverflow.com/a/30632301/5857393

// Some setup code
var c = document.querySelector("canvas"),
  ctx = c.getContext("2d"),
  colors = [{
    r: 255,
    g: 0,
    b: 0
  }, {
    r: 255,
    g: 255,
    b: 0
  }, {
    r: 0,
    g: 255,
    b: 0
  }, {
    r: 0,
    g: 255,
    b: 255
  }, {
    r: 0,
    g: 0,
    b: 255
  }, {
    r: 255,
    g: 0,
    b: 255
  }, {
    r: 0,
    g: 255,
    b: 255
  }, {
    r: 0,
    g: 255,
    b: 0
  }, {
    r: 255,
    g: 255,
    b: 0
  }, ],
  cIndex = 0,
  maxColors = colors.length,
  total = 0,
  segment = 500,
  isDown = false,
  px, py;

setSize();

c.onmousedown = c.ontouchstart = function(e) {
  isDown = true;
  var pos = getPos(e);
  px = pos.x;
  py = pos.y;
};

window.onmousemove = window.ontouchmove = function(e) {
  if (isDown) plot(e);
};
window.onmouseup = window.ontouchend = function(e) {
  e.preventDefault();
  isDown = false;
};

function getPos(e) {
  e.preventDefault();
  if (e.touches) e = e.touches[0];
  var r = c.getBoundingClientRect();
  return {
    x: e.clientX - r.left,
    y: e.clientY - r.top
  }
}

function plot(e) {
  var pos = getPos(e);
  plotLine(ctx, px, py, pos.x, pos.y);
  px = pos.x;
  py = pos.y;
}

function plotLine(ctx, x1, y1, x2, y2) {

  var diffX = Math.abs(x2 - x1),
    diffY = Math.abs(y2 - y1),
    dist = Math.sqrt(diffX * diffX + diffY * diffY),
    step = dist / 50,
    i = 0,
    t, b, x, y;

  while (i <= dist) {
    t = Math.min(1, i / dist);

    x = x1 + (x2 - x1) * t;
    y = y1 + (y2 - y1) * t;

    ctx.fillStyle = getColor();
    ctx.beginPath();
    ctx.arc(x, y, 10, 0, Math.PI * 2);
    ctx.fill();
    i += step;
  }

  function getColor() {

    var r, g, b, t, c1, c2;

    c1 = colors[cIndex];
    c2 = colors[(cIndex + 1) % maxColors];
    t = Math.min(1, total / segment);

    if (++total > segment) {
      total = 0;
      if (++cIndex >= maxColors) cIndex = 0;
    }

    r = c1.r + (c2.r - c1.r) * t;
    g = c1.g + (c2.g - c1.g) * t;
   ...