JSFiddle - React, Tailwind, and code Playground

by Andrew Dunai

HTML

<a href="#" class="generate">Generate lightning</a>
<div>
  <canvas class="canvas" width="400" height="400"></canvas>
</div>

CSS

.generate {
  padding: 10px;
  border: 1px solid #000;
  display: inline-block;
  color: #000 !important;
  text-transform: uppercase;
  text-decoration: none !important;
  font-family: sans-serif;
  margin: 0 0 1rem;
}

JavaScript

var $canvas = document.querySelector('.canvas');
var ctx = $canvas.getContext('2d');

ctx.fillStyle = '#002';
ctx.strokeStyle = '#FFF';
ctx.imageSmoothingEnabled = true;

var step = function(start, attraction, limit, width, left) {
  if (limit <= 0) {
    return;
  }

	if (width < 0.25) {
//  	width = 0.25;
  }

  //var dx = Math.random() * 20 - 10;
  //var dy = 10;
  var rotated = rotate(0, 0, attraction[0], attraction[1], left ? Math.random() * -45 : Math.random() * 45);

  var end = [start[0] + rotated[0] * Math.random() * 20, start[1] + rotated[1] * Math.random() * 20];

	ctx.beginPath();
	ctx.lineWidth = width;
	ctx.moveTo(start[0], start[1]);
  ctx.lineTo(end[0], end[1]);
  ctx.closePath();
  ctx.stroke();

  if (Math.random() * 100 <= 10) {
    var rotated1 = rotate(0, 0, rotated[0], rotated[1], -22.5);
    var rotated2 = rotate(0, 0, rotated[0], rotated[1], 22.5);
    step(end, rotated1, limit - 2 * Math.random(), width * 0.9, true);
    step(end, rotated2, limit - 2 * Math.random(), width * 0.9, false);
  } else {
    step(end, rotated, limit - 2 * Math.random(), width * 0.9, !left);
  }
};

function rotate(cx, cy, x, y, angle) {
  var radians = (Math.PI / 180) * angle,
    cos = Math.cos(radians),
    sin = Math.sin(radians),
    nx = (cos * (x - cx)) + (sin * (y - cy)) + cx,
    ny = (cos * (y - cy)) - (sin * (x - cx)) + cy;
  return [nx, ny];
}

var makeNew = function() {
  ctx.rect(0, 0, 400, 400);
  ctx.fill();
  step([200, 0], [0, 1], 25, 5, Math.random() >= 0.5);
  //alert(rotate(0, 0, 0, 1, 45));
};

document.querySelector('.generate').addEventListener('click', makeNew);
makeNew();