sysolution/dist/static/js/AnimOnScroll.js

178 lines
5.9 KiB
JavaScript

/**
* animOnScroll.js v1.0.0
* http://www.codrops.com
*
* Licensed under the MIT license.
* http://www.opensource.org/licenses/mit-license.php
*
* Copyright 2013, Codrops
* http://www.codrops.com
*/
; (function (window) {
'use strict';
var docElem = window.document.documentElement;
function getViewportH() {
var client = docElem['clientHeight'],
inner = window['innerHeight'];
if (client < inner)
return inner;
else
return client;
}
function scrollY() {
return window.pageYOffset || docElem.scrollTop;
}
// http://stackoverflow.com/a/5598797/989439
function getOffset(el) {
var offsetTop = 0, offsetLeft = 0;
do {
if (!isNaN(el.offsetTop)) {
offsetTop += el.offsetTop;
}
if (!isNaN(el.offsetLeft)) {
offsetLeft += el.offsetLeft;
}
} while (el = el.offsetParent)
return {
top: offsetTop,
left: offsetLeft
}
}
function inViewport(el, h) {
var elH = el.offsetHeight,
scrolled = scrollY(),
viewed = scrolled + getViewportH(),
elTop = getOffset(el).top,
elBottom = elTop + elH,
// if 0, the element is considered in the viewport as soon as it enters.
// if 1, the element is considered in the viewport only when it's fully inside
// value in percentage (1 >= h >= 0)
h = h || 0;
return (elTop + elH * h) <= viewed && (elBottom - elH * h) >= scrolled;
}
function extend(a, b) {
for (var key in b) {
if (b.hasOwnProperty(key)) {
a[key] = b[key];
}
}
return a;
}
function AnimOnScroll(el, options) {
this.el = el;
this.options = extend(this.defaults, options);
this._init();
}
AnimOnScroll.prototype = {
defaults: {
// Minimum and a maximum duration of the animation (random value is chosen)
minDuration: 0,
maxDuration: 0,
// The viewportFactor defines how much of the appearing item has to be visible in order to trigger the animation
// if we'd use a value of 0, this would mean that it would add the animation class as soon as the item is in the viewport.
// If we were to use the value of 1, the animation would only be triggered when we see all of the item in the viewport (100% of it)
viewportFactor: 0
},
_init: function () {
this.items = Array.prototype.slice.call(document.querySelectorAll('#' + this.el.id + ' > li'));
this.itemsCount = this.items.length;
this.itemsRenderedCount = 0;
this.didScroll = false;
var self = this;
imagesLoaded(this.el, function () {
// initialize masonry
new Masonry(self.el, {
itemSelector: 'li',
transitionDuration: 0
});
if (Modernizr.cssanimations) {
// the items already shown...
self.items.forEach(function (el, i) {
if (inViewport(el)) {
self._checkTotalRendered();
classie.add(el, 'shown');
}
});
// animate on scroll the items inside the viewport
window.addEventListener('scroll', function () {
self._onScrollFn();
}, false);
window.addEventListener('resize', function () {
self._resizeHandler();
}, false);
}
});
},
_onScrollFn: function () {
var self = this;
if (!this.didScroll) {
this.didScroll = true;
setTimeout(function () { self._scrollPage(); }, 60);
}
},
_scrollPage: function () {
var self = this;
this.items.forEach(function (el, i) {
if (!classie.has(el, 'shown') && !classie.has(el, 'animate') && inViewport(el, self.options.viewportFactor)) {
setTimeout(function () {
var perspY = scrollY() + getViewportH() / 2;
self.el.style.WebkitPerspectiveOrigin = '50% ' + perspY + 'px';
self.el.style.MozPerspectiveOrigin = '50% ' + perspY + 'px';
self.el.style.perspectiveOrigin = '50% ' + perspY + 'px';
self._checkTotalRendered();
if (self.options.minDuration && self.options.maxDuration) {
var randDuration = (Math.random() * (self.options.maxDuration - self.options.minDuration) + self.options.minDuration) + 's';
el.style.WebkitAnimationDuration = randDuration;
el.style.MozAnimationDuration = randDuration;
el.style.animationDuration = randDuration;
}
classie.add(el, 'animate');
}, 25);
}
});
this.didScroll = false;
},
_resizeHandler: function () {
var self = this;
function delayed() {
self._scrollPage();
self.resizeTimeout = null;
}
if (this.resizeTimeout) {
clearTimeout(this.resizeTimeout);
}
this.resizeTimeout = setTimeout(delayed, 1000);
},
_checkTotalRendered: function () {
++this.itemsRenderedCount;
if (this.itemsRenderedCount === this.itemsCount) {
window.removeEventListener('scroll', this._onScrollFn);
}
}
}
// add to global namespace
window.AnimOnScroll = AnimOnScroll;
})(window);