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...