xxxxxxxxxx
// 2024.0407 initial version
// 2024.0421 add resize and fix flashing
// 2024.0921 resize font according to length [up to 99999]
// 2024.1227 add Helvetica-like font, but probably a mono-spacing to prevent number shifting
// 2025.0203 switch font to 'Fragment Mono'; however there is a noticeable gap between the 1 and the 3
// cdn.jsdelivr.net/npm/@fontsource/fragment-mono@5.1.1/files/fragment-mono-latin-400-normal.woff
// 2025.0228 update to p5.js 1.11.3
// 2025.0310 switch font to 'Overpass Mono'; less gap, but seeking alternatives
// cdnjs.cloudflare.com/ajax/libs/overpass/3.0.4/overpass-mono-webfont/overpass-mono-regular.woff
// 2025.0311 switch font to 'IBM Plex Mono'; this might be the one
// to do:
// add an editable text field to identify the timer purpose
// add option to select time-to-end and then compute the count down
// add optional audio alert and test audio function
// add color selection
let s,w, ct,tt, flash=false, side, fs, fo,
f = 3*60 + 0; // the number of countdown seconds can be set here e.g.: 170=2:50 3600=1 hour
//f=15;
//f = 13*60;
//f = 741;
preload=_=>{
fo = loadFont('https://cdn.jsdelivr.net/npm/@electron-fonts/ibm-plex-mono@1.2.0/fonts/IBMPlexMono-Regular.ttf');
}
setup=_=>{
side = min(windowWidth, windowHeight);
fs = side/3;
createCanvas(windowWidth, windowHeight);
textAlign(c=CENTER,c);
strokeCap(SQUARE);
w=20; // warning color time in seconds
s=f; // save for reset and for basis
frameRate(4);
tt = millis() + f*1000; // targetTime = current + future
textFont(fo);
};
draw=_=>{
let dt=0; // delta
ct = millis();
if(isLooping()) dt = (tt-ct)/1000; // compute and scale to seconds
//background
if(flash){noLoop();dt=0;flash=false;background(0);frameRate(4);}
else
if(dt<0){dt=0;background(255);flash=true;frameRate(16);}
else background(0);
//arc
stroke(255,127,0); //orange
if(dt<=w)stroke(180,0,0); //red
if(dt<=0)stroke(0,180,63); //green
noFill();
strokeWeight(fs/8);
arc(width/2,height/2, 0.75*side,0.75*side, -PI/2+2*PI*((s-dt)%s)/s,PI*3/2);
//number
noStroke();
fill(255,127,0);
if(dt<=w)fill(180,0,0);
if(dt<=0)fill(0,180,63);
let num=ceil(dt);
textSize(num<1000?fs:(num<10000?fs*0.8:fs*0.8*0.8));
text(num, width/2,height/2-fs/16); // +fs/12 -fs/12+5
//button
noStroke();
fill(32);
rect(0,0, fs/2.5,fs/6);
textSize(fs/8);
fill(180,0,180);
text('reset', fs/5,fs/14);
};
windowResized=_=>{
side = min(windowWidth, windowHeight);
fs = side/3;
resizeCanvas(windowWidth, windowHeight);
flash=false;
};
mouseClicked=_=>{
if(mouseX<fs/2.5 && mouseY<fs/6) {
f=s;
tt = millis() + f*1000;
loop();
}
};