Skip to content

Instantly share code, notes, and snippets.

@andreasvirkus
Last active April 19, 2021 14:33
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andreasvirkus/e50ff1c8a3ffd63d9acdf4e8a0133283 to your computer and use it in GitHub Desktop.
Save andreasvirkus/e50ff1c8a3ffd63d9acdf4e8a0133283 to your computer and use it in GitHub Desktop.
A vanilla scrollTop implementation (includes throttle and scrollTo utility functions)
/**
* Vanilla scrollTo implementation (smoothly scroll/"jump" to an element)
* @author github.com/andreasvirkus
*
* Default easing is:
* Robert Penner's easeInOutQuad - http://robertpenner.com/easing/
*
* @param {String} target selector to scroll to
* @param {Object} options Optionally defined duration, offset, callback and easing
*
* @return {void}
*/
export default function jump(target, options) {
target = target === '#' ? (options.offset || 0) : target;
let start = window.pageYOffset,
opt = {
duration: options.duration,
offset: options.offset || 0,
callback: options.callback,
easing: options.easing || easeInOutQuad
},
distance = typeof target === 'string'
? opt.offset + document.querySelector(target).getBoundingClientRect().top
: target,
duration = typeof opt.duration === 'function'
? opt.duration(distance)
: opt.duration,
timeStart, timeElapsed;
requestAnimationFrame(function(time) {
timeStart = time;
loop(time);
});
function loop(time) {
timeElapsed = time - timeStart;
window.scrollTo(0, opt.easing(timeElapsed, start, distance, duration));
console.log('scrolling...', start, timeElapsed);
if (timeElapsed < duration)
requestAnimationFrame(loop);
else
end();
}
function end() {
window.scrollTo(0, start + parseInt(distance, 10));
if (typeof opt.callback === 'function')
opt.callback();
}
function easeInOutQuad(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;
}
}
// Used in the scrollToTop example
function throttle(fn, wait) {
var time = Date.now();
return function() {
if (time + wait - Date.now() < 0) {
fn();
time = Date.now();
}
};
}
/* global throttle jump */
// A simple scrollToTop implementation
(function() {
var toTop = document.getElementById('back-to-top'),
displayOffset = 250,
offset;
showHideTopButton();
window.addEventListener('scroll', throttle(showHideTopButton, 250));
toTop.onclick = function () {
jump('main', {
duration: 200,
callback: function () {
toTop.classList.remove('active');
}
});
};
/**
* Decide whether to show or hide the scrollToTop button
* depending on how far the viewport has been scrolled
*
* @return {void}
*/
function showHideTopButton() {
offset = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
if (offset > displayOffset) {
toTop.classList.add('active');
} else {
toTop.classList.remove('active');
}
}
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment