-
-
Save felipenmoura/650e7e1292c1e7638bcf6c9f9aeb9dd5 to your computer and use it in GitHub Desktop.
ScrollTo animation using pure javascript and no jquery
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Will gracefuly scroll the page | |
* This function will scroll the page using | |
* an `ease-in-out` effect. | |
* | |
* You can use it to scroll to a given element, as well. | |
* To do so, pass the element instead of a number as the position. | |
* Optionally, you can pass a `queryString` for an element selector. | |
* | |
* The default duration is half a second (500ms) | |
* | |
* This function returns a Promise that resolves as soon | |
* as it has finished scrolling. If a selector is passed and | |
* the element is not present in the page, it will reject. | |
* | |
* EXAMPLES: | |
* | |
* ```js | |
* window.scrollPageTo('#some-section', 2000); | |
* window.scrollPageTo(document.getElementById('some-section'), 1000); | |
* window.scrollPageTo(500); // will scroll to 500px in 500ms | |
* ``` | |
* | |
* @returns {Promise} | |
* @param {HTMLElement|Number|Selector} Target | |
* @param {Number} Duration [default=500] | |
* | |
* Inspired by @andjosh's work | |
* | |
*/ | |
function scrollPageTo (to, duration=500) { | |
//t = current time | |
//b = start value | |
//c = change in value | |
//d = duration | |
const easeInOutQuad = function (t, b, c, d) { | |
t /= d/2; | |
if (t < 1) return c/2*t*t + b; | |
t--; | |
return -c/2 * (t*(t-2) - 1) + b; | |
}; | |
return new Promise((resolve, reject) => { | |
const element = document.scrollingElement; | |
if (typeof to === 'string') { | |
to = document.querySelector(to) || reject(); | |
} | |
if (typeof to !== 'number') { | |
to = to.getBoundingClientRect().top + element.scrollTop; | |
} | |
let start = element.scrollTop, | |
change = to - start, | |
currentTime = 0, | |
increment = 20; | |
const animateScroll = function() { | |
currentTime += increment; | |
let val = easeInOutQuad(currentTime, start, change, duration); | |
element.scrollTop = val; | |
if(currentTime < duration) { | |
setTimeout(animateScroll, increment); | |
} else { | |
resolve(); | |
} | |
}; | |
animateScroll(); | |
}); | |
} |
An updated version that satisfies much more strict ESLint parameters, plus new ES syntax:
export const animateScrollTo = (to, duration) => {
const element = document.scrollingElement || document.documentElement;
const start = element.scrollTop;
const change = to - start;
const startDate = +new Date();
// t = current time
// b = start value
// c = change in value
// d = duration
const easeInOutQuad = (t, b, c, d) => {
let t2 = t;
t2 /= d / 2;
if (t2 < 1) return (c / 2) * t2 * t2 + b;
t2 -= 1;
return (-c / 2) * (t2 * (t2 - 2) - 1) + b;
};
const animateScroll = () => {
const currentDate = +new Date();
const currentTime = currentDate - startDate;
element.scrollTop = parseInt(easeInOutQuad(currentTime, start, change, duration), 10);
if (currentTime < duration) {
requestAnimationFrame(animateScroll);
} else {
element.scrollTop = to;
}
};
animateScroll();
};
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks for sharing. Any idea on how to implement it in Angular 7? I've included its reference to angular.json in the scripts array, but don't know how to include the function scrollPageTo in a component.