snail walk clock

clock that shows the next multiple of 5 minutes by adding 1 line at a time like a snail walking

by asteriskman

HTML

<canvas id='cmain' width='250' height='250'></canvas>
<canvas id='cgoal' width='250' height='250'></canvas>
<canvas id='ctest' width='250' height='250'></canvas>

CSS

body {
  background: black;
}

canvas {
  background: white;
}

#ctest {
  display: none;
}

#cgoal {
  display: none;
}

#cmain {
  width: 600px;
  height: 600px;
}

JavaScript

const cmain = document.getElementById('cmain');
const cgoal = document.getElementById('cgoal');
const ctest = document.getElementById('ctest');
const ctxMain = cmain.getContext('2d', {alpha: false});
const ctxGoal = cgoal.getContext('2d', {alpha: false});
const ctxTest = ctest.getContext('2d', {alpha: false});

function getTargetDate() {
  let curDate = new Date();
  let c = 1000 * 60 * 5;
  let targetDate = new Date(Math.round((curDate.getTime() + c/2)/c) * c);
  return targetDate;
}

function getTimeString() {
  let targetDate = getTargetDate();

  let [h,m] = targetDate.toLocaleTimeString().split` `[0].split`:`;
  let baseString = `${h}:${m}`;
  let addSpaces = false;
  let displayString;
  if (addSpaces) {
    displayString = baseString.split``.join` `;
  } else {
    displayString = baseString;
  }
  return displayString;
}

function drawGoal() {
  let ctx = ctxGoal;
  ctx.save();
  //ctx.clearRect(0, 0, cgoal.width, cgoal.height);
  ctx.fillStyle = '#FFFFFF';
  ctx.fillStyle = '#000000';
  ctx.fillRect(0, 0, cgoal.width, cgoal.height);
  ctx.translate(cgoal.width * 0.5, cgoal.height * 0.5);
  ctx.textAlign = 'center';
  ctx.textBaseline = 'middle';
  //let fontSize = 60 * cgoal.width / 300;
  //ctx.font = `${fontSize}px "Arial Black"`;
  let fontSize = 80 * cmain.width / 300;
  //ctx.font = `${fontSize}px "Arial Black"`;
  ctx.font = `bold ${fontSize}px  "Courier New"`;
  ctx.fillStyle = '#FFFFFF';
  let displayString = getTimeString();
  let s = 3;
  for (let dx = -s; dx < s; dx++) {
    for (let dy = -s; dy < s; dy++) {
      ctx.fillText(displayString, dx, dy);
    }
  }

  //ctx.fillText(displayString, 0, 0);
  ctx.restore();
  goalData = undefined;
}

function textAtPointAndAngle(context, x, y, angle, text) {
  context.save();
  context.translate(x, y);
  context.rotate(-angle);
  context.fillText(text, 0, 0);
  context.restore();
}

let numPins = 100;
let radius = cmain.width * 0.5;

function moveToPin(ctx, n, drawLine) {
  let angle = Math.PI * 2 * n...