For demonstration of the issue please see here:
https://gyazo.com/06e423d07afecfa2fbdb06a6da77f66a
I'm getting a jumping behavior on un-pausing the notification. This is also influenced by how long the mouse stays on the notification and how close the progress is to the end.
I've tried so many things, I'm not sure anymore if the problem is truly with setTimeout.
It is like as if since the calculation of this.timerFinishesAt to the first iteration of requestAnimationFrame the progress jumps due to waiting on cpu time? But then again, why would it be influenced by the hover time and progress.
How do I mitigate the jumping behavior?
I read/tried to implement the fix from the following resources amongst looking at other stackoverflow questions:
https://gist.github.com/tanepiper/4215634
How to create an accurate timer in javascript?
What is the reason JavaScript setTimeout is so inaccurate?
https://www.sitepoint.com/creating-accurate-timers-in-javascript/
https://github.com/Falc/Tock.js/tree/master
https://github.com/philipyoungg/timer
https://github.com/Aaronik/accurate_timer
https://github.com/husa/timer.js
timerStart(){
// new future date = future date + elapsed time since pausing
this.timerFinishesAt = new Date( this.timerFinishesAt.getTime() + (Date.now() - this.timerPausedAt.getTime()) );
// set new timeout
this.timerId = window.setTimeout(this.toggleVisibility, (this.timerFinishesAt.getTime() - Date.now()));
// animation start
this.progressId = requestAnimationFrame(this.progressBar);
},
timerPause(){
// stop notification from closing
window.clearTimeout(this.timerId);
// set to null so animation won't stay in a loop
this.timerId = null;
// stop loader animation from progressing
cancelAnimationFrame(this.progressId);
this.progressId = null;
this.timerPausedAt = new Date();
},
progressBar(){
if (this.progress < 100) {
let elapsed = Date.now() - this.timerStarted.getTime();
let wholeTime = this.timerFinishesAt.getTime() - this.timerStarted.getTime();
this.progress = Math.ceil((elapsed / wholeTime) * 100);
if (this.timerId) {
this.progressId = requestAnimationFrame(this.progressBar);
}
} else {
this.progressId = cancelAnimationFrame(this.progressId);
}
}