• File: animeonscroll.js
  • Full Path: /home/chassiw/www/wp-content/themes/kasuari/js/animeonscroll.js
  • File size: 5.38 KB
  • MIME-type: text/plain
  • Charset: utf-8
/**
 * 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 Isotope( 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 );