Answer the question
In order to leave comments, you need to log in
Is it possible to use setTimeout recursively?
I'm trying to write a smooth scrolling function in pure JS. Clicking on the button scrolls to the "catalog" element. At some point, this is what happened:
function scrollToStep(coord = 0, step = 20, temp = 1000) {
if (coord > step) {
setTimeout(function() {
window.scrollBy(0, step);
}, temp);
coord -= step;
console.log(coord);
scrollToStep(coord, step, temp)
} else {
return false;
}
}
buttonChoice.addEventListener('click', function() {
let catalog = document.querySelector('.catalog');
scrollToStep(catalog.getBoundingClientRect().top);
});
Answer the question
In order to leave comments, you need to log in
Move the following call into the body of a function that will execute after a pause:
function scrollToStep(coord = 0, step = 20, pause = 1000) {
if (coord > step) {
setTimeout(function() {
coord -= step;
window.scrollBy(0, step);
scrollToStep(coord, step, pause)
}, pause);
} else {
return false;
}
}
buttonChoice.addEventListener('click', function() {
let catalog = document.querySelector('.catalog');
scrollToStep(catalog.getBoundingClientRect().top);
});
You can use it recursively. But if you want smooth animations, timeouts are not the way to go. You need requestAnimationFrame, and the calculation is there, smoothness is guaranteed. Using the ease function, you can achieve all sorts of scrolling behavior, from nice and smooth, to rubbery, jumpy and funny.
Examples of common functions:
https://gist.github.com/gre/1650294
Demo:
https://jsfiddle.net/profesor08/h7fmcs35/
let currentScrollY = 0;
let targetScrollY = 0;
let t = 0;
document.body.addEventListener("click", () => {
targetScrollY = Math.floor(Math.random() * getScrollheight());
currentScrollY = getScrollTop();
t = 0;
});
function getScrollheight() {
return document.documentElement.scrollHeight || document.body.scrollHeight;
}
function getScrollTop() {
return document.documentElement.scrollTop || document.body.scrollTop;
}
function setScrollTop(to) {
document.documentElement.scrollTop = to;
document.body.scrollTop = to;
}
function ease(t) { return (--t)*t*t+1 }
function animate() {
if (t < 1) {
t += 0.01;
setScrollTop(
currentScrollY + (targetScrollY - currentScrollY) * ease(t)
);
}
requestAnimationFrame(animate);
}
animate();
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question