I am writing a vanilla javascript function to add a page scrolling animation to my website. The problem is that I want the event listener to pause for the specified millisecond time to give time for the animation to complete since if I scroll normally, the animation will happen multiple times one after the other.
/* Event handler for scroll event */
// This is a function which allows a time to be passed in miliseconds. This function will then cause a sleep effect for the specified ms time
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Initial state
var iniState = 0;
// Adding scroll event
window.addEventListener('scroll', function(){
// Detects new state and compares it with the old one
if ((document.body.getBoundingClientRect()).top > iniState)
console.log('up');
else
console.log('down');
// Saves the new position for iteration.
iniState = (document.body.getBoundingClientRect()).top;
sleep(2000).then(() => { console.log("test"); });
});
I tried the timeout function, but this only delayed the event listener instead of pausing for the period of time. This is a link to the console in browser if that makes the problem easier to understand.
In summery, I am trying to make a event listener to listen for a scroll event, then wait 2000 milliseconds to wait for the animation to complete. After this the event listener will then start listening again for a scroll event again.
CodePudding user response:
I believe that every time when a browser detects a scroll event, it'll create a new function using your template and put into to a stack.
For example:
scroll detected : 7:41:20s
call stack = [ function_created_at_7:41:20s
]
The next scroll detected at 7:41:21s :
call stack = [ function_created_at_7:41:20s,
function_created_at_7:41:21s
]
since the promise and timeout are asynchronous execution, they wait and stay in the call stack.
After 2000s passed, sleep's callback of function_created_at_7:41:20s
will be executed
You might have to use global references and some ifs to keep the scroll function into sleep.
CodePudding user response:
let is_waiting = false;
document.addEventListener("scroll",(e) => {
if(!is_waiting) {
console.log("scrolling...");
is_waiting = true;
setTimeout(() => {
is_waiting = false;
},2000);
}
})
CodePudding user response:
let lastScrollStart
window.addEventListener('scroll', () => {
const scrollStart = lastScrollStart = performance.now() // timestamp
const elAnimated = document.querySelector(...)
elAnimated.addEventListener('animationend', function onAnimationEnd() {
elAnimated.removeEventListener('animationend', onAnimationEnd)
if (scrollStart === lastScrollStart) {
...
}
})
})
CodePudding user response:
Just add the event listener, remove it after it's called, then set a timeout to add it again.
function scrollHandler() {
window.removeEventListener('scroll', scrollHandler);
// Detects new state and compares it with the old one
if ((document.body.getBoundingClientRect()).top > iniState)
console.log('up');
else
console.log('down');
// Saves the new position for iteration.
iniState = (document.body.getBoundingClientRect()).top;
setTimeout(() => window.addEventListener('scroll', scrollHandler), 2000);
}
window.addEventListener('scroll', scrollHandler);