How To Make A Countdown Timer Counting Down In Specific Set Of Seconds?
I have the following code: var hours = Math.floor((timeLeft) / 3600); var minutes = Math.floor((timeLeft - (hours * 3600)) / 60); var seconds = Math.floor((timeLeft - (hours * 3600
Solution 1:
Neither setTimeout nor setInterval is accurate and therefore reliable. So instead of accumulating errors on each iteration I prefer to solve this independant of any interval, only using Date.now()
A simple version would be:
//a simple linear equation over time, independant of any intervalfunctionclock(startValue=Date.now(), speed=1){
let m=+speed||0, b=(+startValue||0)-m*Date.now();
//every time you call this function, it will give you //the value for the very moment you call this function//wether you do this every second, every hour of on every framereturnfunctiontime(){
let value = m*Date.now()+b, v = Math.abs(value);
return {
value,
sign: value < 0? "-": "",
ms: Math.floor(value)%1e3,
seconds: Math.floor(v/1e3)%60,
minutes: Math.floor(v/6e4)%60,
hours: Math.floor(v/36e5)%24,
days: Math.floor(v/864e5)
}
}
}
//I find these constants pretty handy when describing timeconstMS=1,SECOND=1e3,SECONDS=SECOND,MINUTE=6e4,MINUTES=MINUTE,HOUR=36e5,HOURS=HOUR,DAY=864e5,DAYS=DAY,WEEK=6048e5,WEEKS=WEEK;
//this is more descriptivelet countDown = clock(24*HOURS, -10*SECONDS / SECOND);
//than this//let countDown = clock(86400000, -10);let output = document.querySelector('#time');
//a helperconstleadingZero = v => String(v).padStart(2,0);
//this is just rendering the current time//it has nothing to do with computing the timesetInterval(function(){
let { sign, hours, minutes, seconds } = countDown();
let hms = [hours, minutes, seconds].map(leadingZero).join(":");
output.textContent = sign + hms;
}, 100);
<divid="time"></div>
But usually I'd use a more complete/versatile implementation
classClock {
constructor(value=Date.now(), speed=1){
this.m = +speed || 0;
this.b = +value || 0;
this.p = true;
}
getvalue(){ returnthis.p? this.b: this.m*Date.now() + this.b }
setvalue(arg){
let value = +arg || 0;
this.b = this.p? value: value - Date.now()*this.m;
}
getpaused(){ returnthis.p }
setpaused(arg){
let pause = !!arg;
if(pause === this.p) return;
this.b += this.m*Date.now() * (pause? 1: -1);
this.p = pause;
}
getspeed(){ returnthis.m }
setspeed(arg){
let speed = +arg || 0;
if(speed === this.m) return;
if(!this.p)
this.b += Date.now() * (this.m-speed);
this.m = speed;
}
valueOf(){ returnthis.value; }
start(){
this.paused = false;
returnthis;
}
stop(){
this.paused = true;
returnthis;
}
time(){
let value = this.value, v = Math.abs(value);
return {
value,
sign: value < 0? "-": "",
ms: Math.floor(value)%1e3,
seconds: Math.floor(v/1e3)%60,
minutes: Math.floor(v/6e4)%60,
hours: Math.floor(v/36e5)%24,
days: Math.floor(v/864e5)
}
}
}
constMS=1,SECOND=1e3,SECONDS=SECOND,MINUTE=6e4,MINUTES=MINUTE,HOUR=36e5,HOURS=HOUR,DAY=864e5,DAYS=DAY,WEEK=6048e5,WEEKS=WEEK;
let speed = this.speed;
let countDown = newClock(24*HOURS-1, speed.value);
let output = document.querySelector('#time');
this.startBtn.onclick = () => countDown.start();
this.stopBtn.onclick = () => countDown.stop();
speed.onchange = speed.onkeyup = () => {
if(!isNaN(+speed.value)) countDown.speed = speed.value;
}
constleadingZero = v => String(v).padStart(2,0);
//this is just rendering the current time//it has nothing to do with computing the timesetInterval(function(){
let { sign, hours, minutes, seconds } = countDown.time();
output.textContent = sign + [hours, minutes, seconds].map(leadingZero).join(":");
}, 100);
console.log(countDown);
<divid="time"></div><inputtype="button"id="startBtn"value="start" /><inputtype="button"id="stopBtn"value="stop" /><inputtype="number"id="speed"value="-2" />
Does this help?
Post a Comment for "How To Make A Countdown Timer Counting Down In Specific Set Of Seconds?"