/** * 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);