Skip to content

Instantly share code, notes, and snippets.

@smashingpat
Last active February 27, 2020 08:54
Show Gist options
  • Save smashingpat/064a07eb5585a2416c5f88132e017b38 to your computer and use it in GitHub Desktop.
Save smashingpat/064a07eb5585a2416c5f88132e017b38 to your computer and use it in GitHub Desktop.
/**
* Calculate the offset in the duration of time ellapsed
*
* @param t time from 0 to 1 (start to end)
*/
const easing = (t) => t * t;
/**
* Scroll to the element with an animation
* @param {HTMLElement} element
* @param {number=200} duration
*/
function scrollToElement(element, duration = 200) {
let animationFrameId = null;
const start = window.pageYOffset;
const startTime = 'now' in window.performance ? performance.now() : new Date().getTime();
const documentHeight = Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);
const windowHeight = window.innerHeight || document.documentElement.clientHeight || document.getElementsByTagName('body')[0].clientHeight;
const elementOffset = typeof element === 'number' ? element : element.offsetTop;
const elementOffsetToScroll = Math.round(documentHeight - elementOffset < windowHeight ? documentHeight - windowHeight : elementOffset);
// if RAF is not supported, there will be no animation and return a noop function
if ('requestAnimationFrame' in window === false) {
window.scroll(0, elementOffsetToScroll);
return function noop() {};
}
function scroll() {
const now = 'now' in window.performance ? performance.now() : new Date().getTime();
const time = Math.min(1, ((now - startTime) / duration));
const easingResult = easing(time);
window.scroll(0, Math.ceil((easingResult * (elementOffsetToScroll - start)) + start));
if (window.pageYOffset === elementOffsetToScroll) {
return;
}
animationFrameId = requestAnimationFrame(scroll);
}
scroll();
return function stopAnimation() {
cancelAnimationFrame(animationFrameId);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment