Skip to content

Instantly share code, notes, and snippets.

@j-quelly
Forked from james2doyle/scrollTo.js
Last active February 5, 2016 01:44
Show Gist options
  • Save j-quelly/8e09515f92d61901ad4b to your computer and use it in GitHub Desktop.
Save j-quelly/8e09515f92d61901ad4b to your computer and use it in GitHub Desktop.
a native scrollTo function in javascript that uses requestAnimationFrame and easing for animation
// get element Y position
function elmYPosition(eID) {
var elm = document.getElementById(eID),
y = elm.offsetTop - 65,
node = elm;
while (node.offsetParent && node.offsetParent != document.body) {
node = node.offsetParent;
y += node.offsetTop;
}
return y;
}
// easing functions http://goo.gl/5HLl8
Math.easeInOutQuad = function(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;
};
Math.easeInCubic = function(t, b, c, d) {
var tc = (t /= d) * t * t;
return b + c * (tc);
};
Math.inOutQuintic = function(t, b, c, d) {
var ts = (t /= d) * t,
tc = ts * t;
return b + c * (6 * tc * ts + -15 * ts * ts + 10 * tc);
};
// requestAnimationFrame for Smart Animating http://goo.gl/sx5sts
var requestAnimFrame = (function() {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
/**
* @param {string} the ID of the element you would like to scroll to
* @param {int} optional integer for duration of scroll, defaults to 500ms
* @param {object} optional options object for callback
* @param {function} optional callback function
*/
function scrollTo(eID, duration, options, callback) {
if (typeof options === 'undefined') {
options = {};
}
// because it's so fucking difficult to detect the scrolling element, just move them all
function move(amount) {
document.documentElement.scrollTop = amount;
document.body.parentNode.scrollTop = amount;
document.body.scrollTop = amount;
}
function position() {
return document.documentElement.scrollTop || document.body.parentNode.scrollTop || document.body.scrollTop;
}
var start = position(),
to = elmYPosition(eID),
change = to - start,
currentTime = 0,
increment = 20;
duration = (typeof(duration) === 'undefined') ? 500 : duration;
var animateScroll = function() {
// increment the time
currentTime += increment;
// find the value with the quadratic in-out easing function
var val = Math.easeInOutQuad(currentTime, start, change, duration);
// move the document.body
move(val);
// do the animation unless its over
if (currentTime < duration) {
requestAnimFrame(animateScroll);
} else {
if (callback && typeof(callback) === 'function') {
// the animation is done so lets callback
callback(options);
}
}
};
animateScroll();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment