Skip to content

Instantly share code, notes, and snippets.

@kimek
Forked from Cosmicist/scroller.js
Created May 16, 2017 12:24
Show Gist options
  • Save kimek/e49946445094e6618f19c8c877356482 to your computer and use it in GitHub Desktop.
Save kimek/e49946445094e6618f19c8c877356482 to your computer and use it in GitHub Desktop.
Vanilla Javascript Scrolling function for easing based scrolling
var Scroller = function(anchors, config)
{
var cfg = compile({
duration: 1000,
offset: 0,
easing: Scroller.easing.inOutQuad,
callback: function() {}
}, config);
[].forEach.call(anchors, function(anchor) {
anchor.addEventListener('click', function(e) {
e.preventDefault();
var target = document.getElementById(
e.target.attributes.href.value.substring(1)
);
scrollTo(
target.offsetTop - cfg.offset,
cfg.duration,
cfg.easing,
cfg.callback
);
});
});
function compile(orig, config)
{
for (var key in config) {
if (config.hasOwnProperty(key)) {
orig[key] = config[key];
}
}
return orig;
}
function scrollTo(Y, duration, easingFunction, callback)
{
var start = Date.now(),
elem = document.documentElement,
from = elem.scrollTop;
if (from === Y) {
callback();
return; /* Prevent scrolling to the Y point if already there */
}
function scroll(timestamp)
{
var currentTime = Date.now(),
time = Math.min(1, ((currentTime - start) / duration)),
easedT = easingFunction(time);
elem.scrollTop = (easedT * (Y - from)) + from;
if (time < 1) {
requestAnimationFrame(scroll);
} else if (callback) {
callback();
}
}
requestAnimationFrame(scroll)
}
}
/*
* Easing Functions - inspired from http://gizma.com/easing/
* only considering the t value for the range [0, 1] => [0, 1]
*/
Scroller.easing = {
// no easing, no acceleration
linear: function (t) { return t },
// accelerating from zero velocity
inQuad: function (t) { return t*t },
// decelerating to zero velocity
outQuad: function (t) { return t*(2-t) },
// acceleration until halfway, then deceleration
inOutQuad: function (t) { return t<.5 ? 2*t*t : -1+(4-2*t)*t },
// accelerating from zero velocity
inCubic: function (t) { return t*t*t },
// decelerating to zero velocity
outCubic: function (t) { return (--t)*t*t+1 },
// acceleration until halfway, then deceleration
inOutCubic: function (t) { return t<.5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1 },
// accelerating from zero velocity
inQuart: function (t) { return t*t*t*t },
// decelerating to zero velocity
outQuart: function (t) { return 1-(--t)*t*t*t },
// acceleration until halfway, then deceleration
inOutQuart: function (t) { return t<.5 ? 8*t*t*t*t : 1-8*(--t)*t*t*t },
// accelerating from zero velocity
inQuint: function (t) { return t*t*t*t*t },
// decelerating to zero velocity
outQuint: function (t) { return 1+(--t)*t*t*t*t },
// acceleration until halfway, then deceleration
inOutQuint: function (t) { return t<.5 ? 16*t*t*t*t*t : 1+16*(--t)*t*t*t*t }
};
/* Add the following to you main js file
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
// requestAnimationFrame polyfill by Erik Möller
// fixes from Paul Irish and Tino Zijdel
(function() {
var lastTime = 0;
var vendors = ['ms', 'moz', 'webkit', 'o'];
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
|| window[vendors[x]+'CancelRequestAnimationFrame'];
}
if (!window.requestAnimationFrame)
window.requestAnimationFrame = function(callback, element) {
var currTime = new Date().getTime();
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
var id = window.setTimeout(function() { callback(currTime + timeToCall); },
timeToCall);
lastTime = currTime + timeToCall;
return id;
};
if (!window.cancelAnimationFrame)
window.cancelAnimationFrame = function(id) {
clearTimeout(id);
};
}()); */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment