Im trying to wrap my head around this function. Mainly the NewTime=time-lastTime; line. Why is it needed? What exactly does it do? From what I gather ir takes the elapsed start time which increments starting at zero. Then takes away the last time we saw which will always leave me with the difference of the two times. But how does it use this to update?
let Count = 0;
let interval = 500;
let lastTime = 0;
function update(time = 0) {
const NewTime = time - lastTime;
lastTime = time;
Count += NewTime;
if (Count > interval) {
player.pos.y++;
Count = 0;
}
draw();
requestAnimationFrame(update);
}
Related
I have a working timer, but it runs from 25 seg every time who the website is visited by a client, I want to synchronise it. F.E. if i visit my webpage in mY Pc, and when it show 15seg left, i visit it from other pc and i want it to show 15 left too.
function timerr(){
var initial = 25000;
var count = initial;
var counter;
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;
if (res<0.1){
document.getElementById("timer").innerHTML = "";
}
else{
tiempo = res.toPrecision(count.toString().length);
tiempo_corto = tiempo.slice(0,-1);
document.getElementById("timer").innerHTML = tiempo_corto;
}
}
clearInterval(counter);
initialMillis = Date.now();
counter = setInterval(timer, 10);
}
If you want everyone to have the same timer count down every 25 seconds and stop at the exact same time, then you can simply use timestamps to keep everything in sync. Here's an example countdown timer that'll restart every 6 seconds (from 5 to 0) and will hit zero at the exact same time for everyone (unless their computer clock is off).
const timerElement = document.getElementById('timer')
const TIMER_DURATION = 6
function step() {
const timestamp = Date.now() / 1000
const timeLeft = (TIMER_DURATION - 1) - Math.round(timestamp) % TIMER_DURATION
timerElement.innerText = timeLeft
const timeCorrection = Math.round(timestamp) - timestamp
setTimeout(step, timeCorrection*1000 + 1000)
}
step()
<p id="timer"></p> seconds
Try it - open this page up in two different tabs and run it. This is set up to automatically account for the fact that setTimeout doesn't always trigger at the delay you asked it to do so (it'll adjust the next setTimeout with a timeCorrection value to correct these issues).
The basic principle is that we're getting the current timestamp and modding it by the amount of time we want this timer to last (6 seconds in the above example). This value will always be the same for everyone, and will always be a number that ranges from 0 to 5. It will also be a number that counts up every second (which is why we then subtract (TIMER_DURATION - 1) from it, to cause the number to count down instead).
After some research, I understand the most accurate way to create a timer in Javascript is to compare the elapsed time from a starting point using date.now() -as this answer suggests.
var startTime = Date.now();
var interval = setInterval(function() {
var elapsedTime = Date.now() - startTime;
var time = (elapsedTime / 1000).toFixed(3);
console.log(time);
}, 10);
This provides the accuracy I am looking for, but I am looking to make this timer reset itself after a certain value (let's say var total = 12000). This value is determined by the length of a video playlist (I am building a 'live' playhead for a video program) and is a variable.
I'm stuck how to go about this, as the counter is counting elapsed time from a certain point in time, it doesn't quite fit the logic of what I am looking for. Any suggestions would be appreciated.
You could use a .setTimeout() at the end of your code to restart your .setInterval(), after the desired time has passed
function runInterval (loopAfter) {
var startTime = Date.now();
var interval = setInterval(function() {
var elapsedTime = Date.now() - startTime;
var time = (elapsedTime / 1000).toFixed(3);
console.log(time);
}, 10);
setTimeout(() => {
clearInterval(interval);
runInterval(loopAfter);
}, loopAfter);
}
runInterval(5000);
Try this:
var startTime = Date.now();
let total = 0;
var interval = setInterval(function() {
if (total === 12000) {
total = 0;
startTime = Date.now();
} else {
total++;
var elapsedTime = Date.now() - startTime;
var time = (elapsedTime / 1000).toFixed(3);
}
console.log(time);
}, 10);
This loop works:
var time;
for (time = 0; time < 5; time++) {
// Runs 5 times
console.log('Log');
}
But this doesn't:
var time;
for (time = 1490543999999999; time <= time - (518400000000 * 10) ; time = time - 518400000000) {
console.log('Log');
}
How come? Is it because the numbers are too large? How to solve this problem then?
Two differences with the first loop:
Since you are traversing in the opposite direction, you need the opposite comparison for the loop condition: > instead of <=.
As you change the time variable, you cannot use it as boundary value. Use a different variable for that -- one that does not change from the initial value
var time, initTime;
for (initTime = time = 1490543999999999; time > initTime - (518400000000 * 10) ; time = time - 518400000000) {
console.log('Log');
}
Or better (to avoid recalculation of the limit):
var time, endTime;
for (time = 1490543999999999, endTime = time - 518400000000 * 10; time > endTime; time -= 518400000000) {
console.log('Log');
}
I am trying to build an accurate countdown timer that shows mins and seconds left. I have tried 2 approaches. Approach 1 uses the setTimer function and calculates the drift. For that approach, some values get skipped and some values get repeated. Approach 2 yields all of the necessary values, but the values are not getting printed to the screen at even intervals (tested in repl.it). How can I make a timer that is both accurate and prints all of the values ?
Approach1:
function countTime(duration) {
var expected = 1;
var secsLeft;
var startT = new Date().getTime();
var oneSecond = 1000;
var expected = startT + oneSecond;
window.setTimeout(step, oneSecond);
function step() {
var nowT = new Date().getTime();
var drift = nowT - expected;
if (drift > oneSecond) {
console.log("drift is over 1 second long!");
}
console.log('drift is ' + drift);
var msDelta = nowT - startT;
var secsLeft = duration - Math.floor(msDelta / 1000);
console.log("secsLeft" + secsLeft);
if (secsLeft === 0) {
++count;
console.log("cleared");
} else {
expected += oneSecond;
setTimeout(step, Math.max(0, oneSecond - drift));
}
}
}
countTime(60);
Approach2:
function countTime(duration) {
var expected = 1;
var secsLeft;
var inter;
var startT = new Date().getTime();
inter = setInterval(function() {
//change in seconds
var sChange = Math.floor((new Date().getTime() - startT) / 1000);
if (sChange === expected) {
expected++;
secsLeft = duration - sChange;
console.log("seconds Left" + secsLeft);
}
if (secsLeft === 0) {
window.clearInterval(inter);
console.log("cleared");
}
}, 100);
}
countTime(60);
Consider using requestAnimationFrame.
function countTime(duration) {
requestAnimationFrame(function(starttime) {
var last = null;
function frame(delta) {
var timeleft = Math.floor(duration - (delta - starttime)/1000),
minutes = Math.floor(timeleft/60),
seconds = timeleft%60;
if( timeleft > 0) {
if( last != timeleft) {
console.log("Time left: "+minutes+"m "+seconds+"s");
last = timeleft;
}
requestAnimationFrame(frame);
}
}
frame(starttime);
});
}
countTime(60);
This will be precise to within the framerate of the browser itself :)
function(){
date = get the date
curSeconds = compute the number of seconds to be displayed
if(oldSeconds!=curSeconds) then refresh display and do oldSeconds = curSeconds;
}
Call this function quite often, the more you call it, the more accurate your timer will be. I advise you to use requestAnimationFrame() instead of setTimout() it will be called 60 times per second (period 16ms) since it is the refresh rate of most displays, it is the maximum visible "accuracy". Also it won't be called when page is not visible.
Simple, clean, no drift over long periods of time.
It also handle not being called for a while.
I'm working on a simple project that is HTML and Javascript; and I have a problem with my timer.
I'm calculating the seconds between two Date() objects; and every 2 seconds, I want to get a new random number. I have a setInterval that runs every 100 ms and when I get past the 2 second mark, the code inside the if statement should run.
So my question is:
How can I make sure the code execute only once per 2 seconds in an if statement that is inside a setInterval() that runs every 100 ms?
Here is the code:
var startTime = new Date();
var endTime = new Date();
var randomNumber = 0;
var gameTimer = setInterval(function(){
//calculate seconds;
var secondsPassed = Math.round( (endTime - startTime) / 1000 );
if(modulo(secondsPassed,2) == 0){
//when the "gate" is open this keep executing every 100 mili seconds.
//but i want it to execute only once every 2 seconds.
randomNumber = Math.floor(Math.random()*lanes.length);
$(lanes[randomNumber]).append(box);
}
endTime = new Date();
}, 100);
var modulo = function (n, m) {
var remain = n % m;
return Math.floor(remain >= 0 ? remain : remain + m);
};
I think you are asking for a double-interval timer.
var interval = 100, beat = 2000, ticks = 0;
var timer = setInterval(function(){
runsEvery100ms(); // ««« Code here runs every 100 ms.
if (ticks > 0 && ticks % beat === 0) {
runsEvery2000ms(); // ««« Code here runs every 2000 ms.
ticks = 0;
}
ticks += interval;
}, interval);
Demo Fiddle here.