JSFiddle - React, Tailwind, and code Playground

HTML

<body>
  <div id="options" sbar>
    <div id="tab"><button>tab</button></div>
    Time<br>
    <input type="number" id="stim" value="10">
    <br>
    <div class="sbs">
      <button id="stat">Start</button>
      <button id="rset" style="display: none;">Resume</button>
    </div>
    Interval<br>
    <div class="sbs">
      <input type="number" id="intv" value="60">
      <input type="number" id="irng" value="60">
    </div>
    Thickness<br>
    <input type="range" id="thic" min="0" max="1" value="0.8" step="0.01">
    <br> 
    Spacing<br>
    <div id="spac">
      <div id="vcot"><input type="range" id="ocen" min="0" max="1" value="0" step="0.01">
      </div>
      <input type="range" id="oedg" min="0" max="1" value="1" step="0.01">
    </div>
    <canvas id="myCanvas"></canvas>
  </div>

  
</body>

CSS

body {
  overflow: hidden;
  background: #202020;
}

.sbs {
  display: flex;
}

.sbs > * {
  min-width: 0;
  flex: 1 1 50%;
}

body[sbar] #options {
  transform: translateX(0);
}

#options {
  font-family:  Arial; 
  color: white;
  position: absolute;
  top: 0px;
  left: 0px;
  bottom: 0px;
  z-index: 999;
  padding: 10px;
  width: 180px;
  transform: translateX(-100%);
  box-sizing: border-box;
  background: rgba(255,255,255,0.1);
  transition: transform 0.5s;
}

#options[sbar] {
  transform: translateX(0);
}

#tab {
  position: absolute;
  left: 100%;
  z-index: 2;
}

#options > input {
  width: 100%;
  box-sizing: border-box;
}

#spac {
  position: relative;
}

#spac input {
  width: 100%;
  z-index: 8;
  margin: 0;
}

#vcot {
  overflow: hidden;
  position: absolute;
  top: 0;
  z-index: 9;
  width: 12px;
}

#myCanvas {
  position: absolute;
  top: 0;
  left: 100%;
  width: 100vw;
  height: 100vh;
  display: block;
  bottom: 0;
  margin: 0;
  border: 0;
  z-index: 1;
  transition: left 0.5s;
}

JavaScript

var canv = document.getElementById("myCanvas");
var ctx = canv.getContext("2d");
var hpi = Math.PI / -2;
var cent = {x:0, y:0}; 
var rad, swid, rspac, iwidth, pause = 0;
var radlim = {min:0, max:1};
var state = 0; // timer operatinal state
var thick = 0.8; // space between rings
var time = 150000; // time
var interval = 16666; // ring depletion rate
var style = 1; // ring depletion behavior
var refill = 1; // make elapsed rings visible but dim
var mod = 0.85; // ring rainbow intensity
var tick = false;
var rings = colors = []; 
var chan = false; //lines when changing

function init(set){
  if(state>1)state = 0; // if finished, reset
  if(time/interval>240) return error(1);
  if(time%interval<1e3)time = ~~(time/interval)*interval; // don't need an extra ring added just because of 0.01 seconds
  rings = [];
  var d = (radlim.max - radlim.min) / Math.ceil(time/interval)
  for(var i=0;i<time/interval;i++){
    rings.push((d*i+radlim.min+d/2)*rad);
  }
  colors = newRainbow(rings.length,mod);
  swid = thick * d * rad + 1;
  rspac = (d*rad-swid)/2;
  //console.log(rings)
  if(set){
    stat.innerHTML = "Pause";
    rset.style.display = "none";
    start = Date.now();
    state = 1;
    console.log("starting");
  }
}

function finish(pre){
  console.log("finished");
  rset.style.display = "none";
  stat.innerHTML = "Start";
  state = 3;
  if(pre){ // if stopped early
    state = 0;
  }
}

function draw(){
  if(trans)resizeCanvas();
  ctx.clearRect(0, 0, cent.x, cent.y);
  var elap;
  if(state < 3){
    switch (state){
      case 0: elap = 0; break;
      case 1: elap = Date.now() - start; break;
      case 2: elap = pause; break;
    }
    if(elap>time) finish(); 
    ctx.lineWidth = swid;
    var a = ((elap-time)%interval/interval);
    if(tick && style<3){ // animated tick
      var s = interval / 1000; // # seconds in interval
      var d = a*s%1;
      a = Math.floor(a*s)/s + (d<-0.2?0:(1+d/0.2)/s);
    }
    if(refill){
      ctx.globalAlpha = 0.3;
      for(var...