Skip to content

Instantly share code, notes, and snippets.

@surjithctly
Created June 29, 2017 14:42
Show Gist options
  • Save surjithctly/87b464ee948908e54bc5ef38a8f88473 to your computer and use it in GitHub Desktop.
Save surjithctly/87b464ee948908e54bc5ef38a8f88473 to your computer and use it in GitHub Desktop.
Smooth Scroll Plugin
/* SmoothScroll for websites v1.2.1. Licensed under the terms of the MIT license.
People involved: Balazs Galambosi (maintainer), Michael Herf (Pulse Algorithm), Edwin Ang (optimzation and added support) */
(function() {
var defaultOptions = {
frameRate: 150,
animationTime: 750,
stepSize: 120,
pulseAlgorithm: true,
pulseScale: 8,
pulseNormalize: 1,
accelerationDelta: 20,
accelerationMax: 1,
keyboardSupport: true,
arrowScroll: 50,
touchpadSupport: true,
fixedBackground: true,
excluded: ""
};
var options = defaultOptions;
var isExcluded = false;
var isFrame = false;
var direction = {
x: 0,
y: 0
};
var initDone = false;
var root = document.documentElement;
var activeElement;
var observer;
var deltaBuffer = [120, 120, 120];
var key = {
left: 37,
up: 38,
right: 39,
down: 40,
spacebar: 32,
pageup: 33,
pagedown: 34,
end: 35,
home: 36
};
var options = defaultOptions;
function initTest() {
var disableKeyboard = false;
if (disableKeyboard) {
removeEvent("keydown", keydown)
}
;if (options.keyboardSupport && !disableKeyboard) {
addEvent("keydown", keydown)
}
;
}
function init() {
if (!document.body)
return;
var e = document.body;
var t = document.documentElement;
var n = window.innerHeight;
var r = e.scrollHeight;
root = document.compatMode.indexOf("CSS") >= 0 ? t : e;
activeElement = e;
initTest();
initDone = true;
if (top != self) {
isFrame = true
} else if (r > n && (e.offsetHeight <= n || t.offsetHeight <= n)) {
var i = false;
var s = function() {
if (!i && t.scrollHeight != document.height) {
i = true;
setTimeout(function() {
t.style.height = document.height + "px";
i = false
}, 500)
}
};
t.style.height = "auto";
setTimeout(s, 10);
if (root.offsetHeight <= n) {
var o = document.createElement("div");
o.style.clear = "both";
e.appendChild(o)
}
}
if (!options.fixedBackground && !isExcluded) {
e.style.backgroundAttachment = "scroll";
t.style.backgroundAttachment = "scroll"
}
}
function scrollArray(e, t, n, r) {
r || (r = 1e3);
directionCheck(t, n);
if (options.accelerationMax != 1) {
var i = +(new Date);
var s = i - lastScroll;
if (s < options.accelerationDelta) {
var o = (1 + 30 / s) / 2;
if (o > 1) {
o = Math.min(o, options.accelerationMax);
t *= o;
n *= o
}
}
lastScroll = +(new Date)
}
que.push({
x: t,
y: n,
lastX: t < 0 ? .99 : -.99,
lastY: n < 0 ? .99 : -.99,
start: +(new Date)
});
if (pending) {
return
}
var u = e === document.body;
var a = function(i) {
var s = +(new Date);
var o = 0;
var f = 0;
for (var l = 0; l < que.length; l++) {
var c = que[l];
var h = s - c.start;
var p = h >= options.animationTime;
var d = p ? 1 : h / options.animationTime;
if (options.pulseAlgorithm) {
d = pulse(d)
}
var v = c.x * d - c.lastX >> 0;
var m = c.y * d - c.lastY >> 0;
o += v;
f += m;
c.lastX += v;
c.lastY += m;
if (p) {
que.splice(l, 1);
l--
}
}
if (u) {
window.scrollBy(o, f)
} else {
if (o)
e.scrollLeft += o;
if (f)
e.scrollTop += f
}
if (!t && !n) {
que = []
}
if (que.length) {
requestFrame(a, e, r / options.frameRate + 1)
} else {
pending = false
}
};
requestFrame(a, e, 0);
pending = true
}
function wheel(e) {
if (!initDone) {
init()
}
var t = e.target;
var n = overflowingAncestor(t);
if (!n || e.defaultPrevented || isNodeName(activeElement, "embed") || isNodeName(t, "embed") && /\.pdf/i.test(t.src)) {
return true
}
var r = e.wheelDeltaX || 0;
var i = e.wheelDeltaY || 0;
if (!r && !i) {
i = e.wheelDelta || 0
}
if (!options.touchpadSupport && isTouchpad(i)) {
return true
}
if (Math.abs(r) > 1.2) {
r *= options.stepSize / 120
}
if (Math.abs(i) > 1.2) {
i *= options.stepSize / 120
}
scrollArray(n, -r, -i);
e.preventDefault()
}
function keydown(e) {
var t = e.target;
var n = e.ctrlKey || e.altKey || e.metaKey || e.shiftKey && e.keyCode !== key.spacebar;
if (/input|textarea|select|embed/i.test(t.nodeName) || t.isContentEditable || e.defaultPrevented || n) {
return true
}
if (isNodeName(t, "button") && e.keyCode === key.spacebar) {
return true
}
var r, i = 0, s = 0;
var o = overflowingAncestor(activeElement);
var u = o.clientHeight;
if (o == document.body) {
u = window.innerHeight
}
switch (e.keyCode) {
case key.up:
s = -options.arrowScroll;
break;
case key.down:
s = options.arrowScroll;
break;
case key.spacebar:
r = e.shiftKey ? 1 : -1;
s = -r * u * .9;
break;
case key.pageup:
s = -u * .9;
break;
case key.pagedown:
s = u * .9;
break;
case key.home:
s = -o.scrollTop;
break;
case key.end:
var a = o.scrollHeight - o.scrollTop - u;
s = a > 0 ? a + 10 : 0;
break;
case key.left:
i = -options.arrowScroll;
break;
case key.right:
i = options.arrowScroll;
break;
default:
return true
}
scrollArray(o, i, s);
e.preventDefault()
}
var que = [];
var pending = false;
var lastScroll = +(new Date);
function mousedown(e) {
activeElement = e.target
}
function setCache(e, t) {
for (var n = e.length; n--; )
cache[uniqueID(e[n])] = t;
return t
}
function overflowingAncestor(e) {
var t = [];
var n = root.scrollHeight;
do {
var r = cache[uniqueID(e)];
if (r) {
return setCache(t, r)
}
t.push(e);
if (n === e.scrollHeight) {
if (!isFrame || root.clientHeight + 10 < n) {
return setCache(t, document.body)
}
} else if (e.clientHeight + 10 < e.scrollHeight) {
overflow = getComputedStyle(e, "").getPropertyValue("overflow-y");
if (overflow === "scroll" || overflow === "auto") {
return setCache(t, e)
}
}
} while (e = e.parentNode)
}
function addEvent(e, t, n) {
window.addEventListener(e, t, n || false)
}
function removeEvent(e, t, n) {
window.removeEventListener(e, t, n || false)
}
function isNodeName(e, t) {
return (e.nodeName || "").toLowerCase() === t.toLowerCase()
}
function directionCheck(e, t) {
e = e > 0 ? 1 : -1;
t = t > 0 ? 1 : -1;
if (direction.x !== e || direction.y !== t) {
direction.x = e;
direction.y = t;
que = [];
lastScroll = 0
}
}
function isTouchpad(e) {
if (!e)
return;
e = Math.abs(e);
deltaBuffer.push(e);
deltaBuffer.shift();
clearTimeout(deltaBufferTimer);
var t = isDivisible(deltaBuffer[0], 120) && isDivisible(deltaBuffer[1], 120) && isDivisible(deltaBuffer[2], 120);
return !t
}
function isDivisible(e, t) {
return Math.floor(e / t) == e / t
}
function pulse_(e) {
var t, n, r;
e = e * options.pulseScale;
if (e < 1) {
t = e - (1 - Math.exp(-e))
} else {
n = Math.exp(-1);
e -= 1;
r = 1 - Math.exp(-e);
t = n + r * (1 - n)
}
return t * options.pulseNormalize
}
var cache = {};
setInterval(function() {
cache = {}
}, 10 * 1e3);
var uniqueID = function() {
var e = 0;
return function(t) {
return t.uniqueID || (t.uniqueID = e++)
}
}();
var deltaBufferTimer;
var requestFrame = function() {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || function(e, t, n) {
window.setTimeout(e, n || 1e3 / 60)
}
}();
function pulse(e) {
if (e >= 1)
return 1;
if (e <= 0)
return 0;
if (options.pulseNormalize == 1) {
options.pulseNormalize /= pulse_(1)
}
return pulse_(e)
}
var isSupportedBrowser = /chrome/i.test(window.navigator.userAgent) ? true : /safari/i.test(window.navigator.userAgent);
var wheelEvent = null;
if ("onwheel"in document.createElement("div"))
wheelEvent = "wheel";
else if ("onmousewheel"in document.createElement("div"))
wheelEvent = "mousewheel";
if (wheelEvent && isSupportedBrowser) {
addEvent(wheelEvent, wheel);
addEvent("mousedown", mousedown);
addEvent("load", init)
}
})();
/* SmoothScroll for websites v1.2.1. Licensed under the terms of the MIT license. People involved: Balazs Galambosi (maintainer), Michael Herf (Pulse Algorithm), Edwin Ang (optimzation and added support) */ (function(){var defaultOptions={frameRate: 150,animationTime: 750,stepSize: 120,pulseAlgorithm: true,pulseScale: 8,pulseNormalize: 1,accelerationDelta: 20,accelerationMax: 1,keyboardSupport: true,arrowScroll: 50,touchpadSupport: true,fixedBackground: true, excluded: ""};var options = defaultOptions;var isExcluded=false;var isFrame=false;var direction={x:0,y:0};var initDone=false;var root=document.documentElement;var activeElement;var observer;var deltaBuffer=[120,120,120];var key={left:37,up:38,right:39,down:40,spacebar:32,pageup:33,pagedown:34,end:35,home:36};var options = defaultOptions;function initTest() {var disableKeyboard = false; if(disableKeyboard){removeEvent("keydown", keydown)}; if (options.keyboardSupport && !disableKeyboard){addEvent("keydown", keydown)};}function init(){if(!document.body)return;var e=document.body;var t=document.documentElement;var n=window.innerHeight;var r=e.scrollHeight;root=document.compatMode.indexOf("CSS")>=0?t:e;activeElement=e;initTest();initDone=true;if(top!=self){isFrame=true}else if(r>n&&(e.offsetHeight<=n||t.offsetHeight<=n)){var i=false;var s=function(){if(!i&&t.scrollHeight!=document.height){i=true;setTimeout(function(){t.style.height=document.height+"px";i=false},500)}};t.style.height="auto";setTimeout(s,10);if(root.offsetHeight<=n){var o=document.createElement("div");o.style.clear="both";e.appendChild(o)}}if(!options.fixedBackground&&!isExcluded){e.style.backgroundAttachment="scroll";t.style.backgroundAttachment="scroll"}}function scrollArray(e,t,n,r){r||(r=1e3);directionCheck(t,n);if(options.accelerationMax!=1){var i=+(new Date);var s=i-lastScroll;if(s<options.accelerationDelta){var o=(1+30/s)/2;if(o>1){o=Math.min(o,options.accelerationMax);t*=o;n*=o}}lastScroll=+(new Date)}que.push({x:t,y:n,lastX:t<0?.99:-.99,lastY:n<0?.99:-.99,start:+(new Date)});if(pending){return}var u=e===document.body;var a=function(i){var s=+(new Date);var o=0;var f=0;for(var l=0;l<que.length;l++){var c=que[l];var h=s-c.start;var p=h>=options.animationTime;var d=p?1:h/options.animationTime;if(options.pulseAlgorithm){d=pulse(d)}var v=c.x*d-c.lastX>>0;var m=c.y*d-c.lastY>>0;o+=v;f+=m;c.lastX+=v;c.lastY+=m;if(p){que.splice(l,1);l--}}if(u){window.scrollBy(o,f)}else{if(o)e.scrollLeft+=o;if(f)e.scrollTop+=f}if(!t&&!n){que=[]}if(que.length){requestFrame(a,e,r/options.frameRate+1)}else{pending=false}};requestFrame(a,e,0);pending=true}function wheel(e){if(!initDone){init()}var t=e.target;var n=overflowingAncestor(t);if(!n||e.defaultPrevented||isNodeName(activeElement,"embed")||isNodeName(t,"embed")&&/\.pdf/i.test(t.src)){return true}var r=e.wheelDeltaX||0;var i=e.wheelDeltaY||0;if(!r&&!i){i=e.wheelDelta||0}if(!options.touchpadSupport&&isTouchpad(i)){return true}if(Math.abs(r)>1.2){r*=options.stepSize/120}if(Math.abs(i)>1.2){i*=options.stepSize/120}scrollArray(n,-r,-i);e.preventDefault()}function keydown(e){var t=e.target;var n=e.ctrlKey||e.altKey||e.metaKey||e.shiftKey&&e.keyCode!==key.spacebar;if(/input|textarea|select|embed/i.test(t.nodeName)||t.isContentEditable||e.defaultPrevented||n){return true}if(isNodeName(t,"button")&&e.keyCode===key.spacebar){return true}var r,i=0,s=0;var o=overflowingAncestor(activeElement);var u=o.clientHeight;if(o==document.body){u=window.innerHeight}switch(e.keyCode){case key.up:s=-options.arrowScroll;break;case key.down:s=options.arrowScroll;break;case key.spacebar:r=e.shiftKey?1:-1;s=-r*u*.9;break;case key.pageup:s=-u*.9;break;case key.pagedown:s=u*.9;break;case key.home:s=-o.scrollTop;break;case key.end:var a=o.scrollHeight-o.scrollTop-u;s=a>0?a+10:0;break;case key.left:i=-options.arrowScroll;break;case key.right:i=options.arrowScroll;break;default:return true}scrollArray(o,i,s);e.preventDefault()}var que=[];var pending=false;var lastScroll=+(new Date);function mousedown(e){activeElement=e.target}function setCache(e,t){for(var n=e.length;n--;)cache[uniqueID(e[n])]=t;return t}function overflowingAncestor(e){var t=[];var n=root.scrollHeight;do{var r=cache[uniqueID(e)];if(r){return setCache(t,r)}t.push(e);if(n===e.scrollHeight){if(!isFrame||root.clientHeight+10<n){return setCache(t,document.body)}}else if(e.clientHeight+10<e.scrollHeight){overflow=getComputedStyle(e,"").getPropertyValue("overflow-y");if(overflow==="scroll"||overflow==="auto"){return setCache(t,e)}}}while(e=e.parentNode)}function addEvent(e,t,n){window.addEventListener(e,t,n||false)}function removeEvent(e,t,n){window.removeEventListener(e,t,n||false)}function isNodeName(e,t){return(e.nodeName||"").toLowerCase()===t.toLowerCase()}function directionCheck(e,t){e=e>0?1:-1;t=t>0?1:-1;if(direction.x!==e||direction.y!==t){direction.x=e;direction.y=t;que=[];lastScroll=0}}function isTouchpad(e){if(!e)return;e=Math.abs(e);deltaBuffer.push(e);deltaBuffer.shift();clearTimeout(deltaBufferTimer);var t=isDivisible(deltaBuffer[0],120)&&isDivisible(deltaBuffer[1],120)&&isDivisible(deltaBuffer[2],120);return!t}function isDivisible(e,t){return Math.floor(e/t)==e/t}function pulse_(e){var t,n,r;e=e*options.pulseScale;if(e<1){t=e-(1-Math.exp(-e))}else{n=Math.exp(-1);e-=1;r=1-Math.exp(-e);t=n+r*(1-n)}return t*options.pulseNormalize}var cache={};setInterval(function(){cache={}},10*1e3);var uniqueID=function(){var e=0;return function(t){return t.uniqueID||(t.uniqueID=e++)}}();var deltaBufferTimer;var requestFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||function(e,t,n){window.setTimeout(e,n||1e3/60)}}();function pulse(e){if(e>=1)return 1;if(e<=0)return 0;if(options.pulseNormalize==1){options.pulseNormalize/=pulse_(1)}return pulse_(e)}var isSupportedBrowser=/chrome/i.test(window.navigator.userAgent)?true:/safari/i.test(window.navigator.userAgent);var wheelEvent=null;if("onwheel"in document.createElement("div"))wheelEvent="wheel";else if("onmousewheel"in document.createElement("div"))wheelEvent="mousewheel";if(wheelEvent&&isSupportedBrowser){addEvent(wheelEvent,wheel);addEvent("mousedown",mousedown);addEvent("load",init)}})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment