I have a very basic lightweight function that counts down from 30 seconds. I have been trying to add milliseconds to it but I can't seem to get it to work correctly.
var count = 30;
var counter = setInterval(timer, 1000); //1000 will run it every 1 second
function timer() {
if (count <= 0) {
clearInterval(counter);
return;
}
count = count - 1;
document.getElementById("timer").innerHTML = count + " secs"; // watch for spelling
}
Try it this way. Stopwatches only count hundredths of seconds anyway.
var count = 3000;
var counter = setInterval(timer, 10); //10 will run it every 100th of a second
function timer()
{
if (count <= 0)
{
clearInterval(counter);
return;
}
count--;
document.getElementById("timer").innerHTML=count /100+ " secs";
}
Just for better formatting and testing:
HTML
<span id="timer"></span>
<button id="start">start</button>
<button id="stop">stop</button>
<button id="reset">reset</button>
Javascript
var initial = 30000;
var count = initial;
var counter; //10 will run it every 100th of a second
function timer() {
if (count <= 0) {
clearInterval(counter);
return;
}
count--;
displayCount(count);
}
function displayCount(count) {
var res = count / 100;
document.getElementById("timer").innerHTML = res.toPrecision(count.toString().length) + " secs";
}
$('#start').on('click', function () {
clearInterval(counter);
counter = setInterval(timer, 10);
});
$('#stop').on('click', function () {
clearInterval(counter);
});
$('#reset').on('click', function () {
clearInterval(counter);
count = initial;
displayCount(count);
});
displayCount(initial);
EDIT:
The original question was trying to figure out how to make a display like a stopwatch, and I know very few that actually count milliseconds. That being said, here is a possible solution to do that. It relies on updating as fast as possible, and getting the difference between our last update and our current one to remain accurate.
var initial = 300000;
var count = initial;
var counter; //10 will run it every 100th of a second
var initialMillis;
function timer() {
if (count <= 0) {
clearInterval(counter);
return;
}
var current = Date.now();
count = count - (current - initialMillis);
initialMillis = current;
displayCount(count);
}
function displayCount(count) {
var res = count / 1000;
document.getElementById("timer").innerHTML = res.toPrecision(count.toString().length) + " secs";
}
$('#start').on('click', function () {
clearInterval(counter);
initialMillis = Date.now();
counter = setInterval(timer, 1);
});
$('#stop').on('click', function () {
clearInterval(counter);
});
$('#reset').on('click', function () {
clearInterval(counter);
count = initial;
displayCount(count);
});
displayCount(initial);
The problem is that the browser can't possibly handle manipulating the DOM every millisecond. For this reason, lots of browsers actually set a minimum value for intervals - and the W3C suggest a minimum of 4ms (source). We can use this information to create a throttled approach which runs as quickly as possible.
// We actually only run our method every x millisecs, due to browser constraints
var THROTTLE_AMOUNT = 4;
countdown(30);
function countdown(secs) {
var milli = secs * (1000);
var counter = setInterval(function() {
if(milli <= 0) {
clearInterval(counter);
return
}
milli -= THROTTLE_AMOUNT;
document.getElementById("timer").innerHTML = milli + " millisecs"; // watch for spelling
}, THROTTLE_AMOUNT);
}
You can try this. If you're targeting modern browsers, you may have access to the Performance
API, which gives high resolution timestamps instead of normal timestamps.
An improved solution would use requestAnimationFrame()
. Updating the DOM every millisecond, even if possible with setTimeout(), is a waste of resources, as the browser will only refresh the screen, typically, 60 times in a second (every 16.6 ms). Updating the clock two times or more in that interval would be useless, and the user will only see the last value.
function now() {
return window.performance ? window.performance.now() : Date.now();
}
var count = 30000;
var delay = 20; //20 ms. This will be only indicative. There's no guarantee the browswer will call the function after exactly this time
var initTick = 0;
var timerElement = document.getElementById("timer");
function tick() {
var remaining = (count - (now() - initTick)) / 1000;
console.log(remaining);
remaining = remaining >= 0 ? remaining : 0;
var secs = remaining.toFixed(2);
timerElement.innerHTML = secs + " secs";
if (remaining) setTimeout(tick, delay);
}
initTick = now();
console.log(now());
setTimeout(tick, delay);
JSFIDDLE.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With