@randstad-design/orbit-multitheme
Version:
multitheme Front-end code based on Randstad Human Forward components
56 lines (48 loc) • 1.63 kB
JavaScript
function getElementY(query) {
return window.pageYOffset + query.getBoundingClientRect().top;
}
module.exports = function scrollToElement(
element,
duration = 100,
addspace = 0
) {
if (!element) {
return;
}
const startingY = window.pageYOffset;
const elementY =
element === 'top' ? getElementY(document.body) : getElementY(element);
// If element is close to page's bottom then window will scroll only to some position above the element.
const targetY =
document.body.scrollHeight - elementY < window.innerHeight
? document.body.scrollHeight - window.innerHeight
: elementY;
const diff = targetY - startingY + addspace;
// Easing function: easeInOutCubic
// From: https://gist.github.com/gre/1650294
const easing = t => {
return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;
};
let start;
if (!diff) {
return;
}
// Bootstrap our animation - it will get called right before next frame shall be rendered.
window.requestAnimationFrame(function step(timestamp) {
if (!start) {
start = timestamp;
}
// Elapsed miliseconds since start of scrolling.
const time = timestamp - start;
// Get percent of completion in range [0, 1].
let percent = Math.min(time / duration, 1);
// Apply the easing.
// It can cause bad-looking slow frames in browser performance tool, so be careful.
percent = easing(percent);
window.scrollTo(0, startingY + diff * percent);
// Proceed with animation as long as we wanted it to.
if (time < duration) {
window.requestAnimationFrame(step);
}
});
};