JSFiddle - React, Tailwind, and code Playground

by Dogbert

HTML

<canvas id="canvas" width="300" height="300"></canvas>
<pre id="log"></pre>
<canvas id="playback" width="300" height="300"></canvas>
<p>
  <button id="play">Play</button>
</p>

CSS

body {
  text-align: center;
  margin-top: 20px;
}

canvas,
#log {
  border: 1px solid #333;
  width: 300px;
  height: 300px;
  display: inline-block;
  margin: 0;
  padding: 0;
}

#log {
  overflow: auto;
  text-align: left;
  background: white;
}

JavaScript

var el = document.getElementById('canvas');
var ctx = el.getContext('2d');

ctx.lineWidth = 5;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';

var isDrawing, points = [],
  prevTime;

el.addEventListener('mousedown', function(e) {
  isDrawing = true;
  points = [{
    x: e.offsetX,
    y: e.offsetY,
    delay: 0
  }];
  prevTime = +new Date;
  updateLog();
});

el.addEventListener('mousemove', function(e) {
  if (!isDrawing) return;
  points.push({
    x: e.offsetX,
    y: e.offsetY,
    delay: +new Date - prevTime
  });
  prevTime = +new Date;
  updateLog();
  draw(ctx, points);
});

el.addEventListener('mouseup', function() {
  isDrawing = false;
});

var playback = document.getElementById("playback");
var playbackCtx = playback.getContext("2d");
playbackCtx.lineWidth = 5;
playbackCtx.lineJoin = 'round';
playbackCtx.lineCap = 'round';

document.getElementById("play").addEventListener("click", function() {
  play(playbackCtx, points);
})

function updateLog() {
  document.getElementById("log").innerText = JSON.stringify(points, null, 4);
}

function draw(context, points) {
  context.clearRect(0, 0, context.canvas.width, context.canvas.height);

  var p1 = points[0];
  var p2 = points[1];

  context.beginPath();
  context.moveTo(p1.x, p1.y);

  for (var i = 1; i < points.length; i++) {
    context.quadraticCurveTo(p1.x, p1.y, (p1.x + p2.x) / 2, (p1.y + p2.y) / 2);
    p1 = points[i];
    p2 = points[i + 1];
  }

  context.lineTo(p1.x, p1.y);
  context.stroke();
}

function play(context, points) {
  tick(2);

  function tick(i) {
    if (i <= points.length) {
      draw(context, points.slice(0, i));
      setTimeout(function() {
        tick(i + 1)
      }, points[i].delay);
    }
  }
}