diff --git a/src/components/ui/scrollTo.js b/src/components/ui/scrollTo.js new file mode 100644 index 0000000..dbcdbf5 --- /dev/null +++ b/src/components/ui/scrollTo.js @@ -0,0 +1,28 @@ +/** + * Implements scroll to animation with momentum effect + */ + +const requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame + || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; + +const DURATION = 500; +export default function scrollTo(y) { + const start = Date.now(); + const {scrollTop} = document.body; + const delta = y - scrollTop; + + requestAnimationFrame(function animateScroll() { + const elapsed = Date.now() - start; + + let interpolatedY = scrollTop + delta * (elapsed / DURATION); + + if (interpolatedY < y) { + requestAnimationFrame(animateScroll); + } else { + interpolatedY = y; + } + + window.scrollTo(0, interpolatedY); + }); +} + diff --git a/src/index.js b/src/index.js index bb6d117..ec4ebce 100644 --- a/src/index.js +++ b/src/index.js @@ -53,6 +53,7 @@ userFactory(store) }); +import scrollTo from 'components/ui/scrollTo'; const SCROLL_ANCHOR_OFFSET = 80; // 50 + 30 (header height + some spacing) /** * Scrolls to page's top or #anchor link, if any @@ -73,7 +74,7 @@ function restoreScroll() { y = scrollTop + top - SCROLL_ANCHOR_OFFSET; } - window.scrollTo(0, y); + scrollTo(y); }, 100); }