Skip to content

Instantly share code, notes, and snippets.

@ashucg
Created December 12, 2017 12:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ashucg/864e0be8431c890ef0950a1966b4a987 to your computer and use it in GitHub Desktop.
Save ashucg/864e0be8431c890ef0950a1966b4a987 to your computer and use it in GitHub Desktop.
Scroll an element into view
/**
* Scroll an element into view
* @param {Integer} duration in ms
* @param {Object} options such as middle (boolean)
*/
Element.prototype.scrollTo = function(duration, options) {
if (typeof duration === 'undefined' || duration <= 0) {
duration = 1; // Minimum value that can be used
}
if (options === undefined) options = {
middle: false // Bring element to the middle of the page
};
if (options.middle === undefined) options.middle = false;
let negativeOffset = options.middle ? (window.innerHeight / 2) : 0; // Negative offset is required if middle is true
let elemPosition = this.offset().top - negativeOffset; // Get the element position on page
let currentPosition = window.pageYOffset; // Get the current window scroll position from top
let remaining = elemPosition - currentPosition; // Store the pxs that are remaining to be scrolled
let start_ts;
window.requestAnimationFrame(function scroll(ts) {
if (!start_ts) start_ts = ts; // Store start Timestamp if not already
let time = ts - start_ts;
let percent = Math.min(time / duration, 1);
window.scrollTo(0, currentPosition + remaining * percent); // Scroll to new Y-coordinate
if (time < duration) window.requestAnimationFrame(scroll); // Request new AnimationFrame if elapsed time is < duration
});
};
/**
* Calculates the offset for an element (using the famous hack)
* @return {Object} returns top and left offset
*/
Element.prototype.offset = function() {
let elem = this;
let l = 0;
let t = 0;
while (elem && !isNaN(elem.offsetLeft) && !isNaN(elem.offsetTop)) {
l += elem.offsetLeft - elem.scrollLeft;
t += elem.offsetTop - elem.scrollTop;
elem = elem.offsetParent;
}
return {
top: t,
left: l
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment