cn.status.im/js/lib/animatescroll.js

87 lines
2.7 KiB
JavaScript

// AnimateScroll.js
// Sunmock Yang Nov. 2015
function animateScroll(target, duration, easing, padding, align, onFinish) {
padding = padding ? padding : 0;
var docElem = document.documentElement; // to facilitate minification better
var windowHeight = docElem.clientHeight;
var maxScroll = ( 'scrollMaxY' in window ) ? window.scrollMaxY : (docElem.scrollHeight - windowHeight);
var currentY = window.pageYOffset;
var targetY = currentY;
var elementBounds = isNaN(target) ? target.getBoundingClientRect() : 0;
if (align === "center") {
targetY += isNaN(target) ? (elementBounds.top + elementBounds.height/2) : target;
targetY -= windowHeight / 2;
targetY -= padding
}
else if (align === "bottom") {
targetY += elementBounds.bottom || target;
targetY -= windowHeight;
targetY += padding
}
else { // top, undefined
targetY += elementBounds.top || target;
targetY -= padding
}
targetY = Math.max(Math.min(maxScroll, targetY), 0);
var deltaY = targetY - currentY;
var obj = {
targetY: targetY,
deltaY: deltaY,
duration: (duration) ? duration : 0,
easing: (easing in animateScroll.Easing) ? animateScroll.Easing[easing] : animateScroll.Easing.linear,
onFinish: onFinish,
startTime: Date.now(),
lastY: currentY,
step: animateScroll.step,
};
window.requestAnimationFrame(obj.step.bind(obj));
}
// Taken from gre/easing.js
// https://gist.github.com/gre/1650294
animateScroll.Easing = {
linear: function (t) { return t },
easeInQuad: function (t) { return t*t },
easeOutQuad: function (t) { return t*(2-t) },
easeInOutQuad: function (t) { return t<.5 ? 2*t*t : -1+(4-2*t)*t },
easeInCubic: function (t) { return t*t*t },
easeOutCubic: function (t) { return (--t)*t*t+1 },
easeInOutCubic: function (t) { return t<.5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1 },
easeInQuart: function (t) { return t*t*t*t },
easeOutQuart: function (t) { return 1-(--t)*t*t*t },
easeInOutQuart: function (t) { return t<.5 ? 8*t*t*t*t : 1-8*(--t)*t*t*t },
easeInQuint: function (t) { return t*t*t*t*t },
easeOutQuint: function (t) { return 1+(--t)*t*t*t*t },
easeInOutQuint: function (t) { return t<.5 ? 16*t*t*t*t*t : 1+16*(--t)*t*t*t*t }
};
animateScroll.step = function () {
if (this.lastY !== window.pageYOffset && this.onFinish) {
this.onFinish();
return;
}
// Calculate how much time has passed
var t = Math.min((Date.now() - this.startTime) / this.duration, 1);
// Scroll window amount determined by easing
var y = this.targetY - ((1 - this.easing(t)) * (this.deltaY));
window.scrollTo(window.scrollX, y);
// Continue animation as long as duration hasn't surpassed
if (t !== 1) {
this.lastY = window.pageYOffset;
window.requestAnimationFrame(this.step.bind(this));
} else {
if (this.onFinish) this.onFinish();
}
}
module.exports = animateScroll