JAVASCRIPT   66

scrollReveal js

Guest on 2nd July 2022 01:34:30 AM

  1.  
  2. (function(root, factory) {
  3.   if (typeof define === 'function' && define.amd) {
  4.     define(factory);
  5.   } else if (typeof exports === 'object') {
  6.     module.exports = factory(require, exports, module);
  7.   } else {
  8.     root.scrollReveal = factory();
  9.   }
  10. }(this, function(require, exports, module) {
  11.  
  12. /*
  13.                        _ _ _____                      _   _
  14.                       | | |  __ \                    | | (_)
  15.     ___  ___ _ __ ___ | | | |__) |_____   _____  __ _| |  _ ___
  16.    / __|/ __| '__/ _ \| | |  _  // _ \ \ / / _ \/ _` | | | / __|
  17.    \__ \ (__| | | (_) | | | | \ \  __/\ V /  __/ (_| | |_| \__ \
  18.    |___/\___|_|  \___/|_|_|_|  \_\___| \_/ \___|\__,_|_(_) |___/ v2.2.0
  19.                                                         _/ |
  20.                                                        |__/
  21.  
  22. ================================================================================
  23.  
  24.    scrollReveal.js (c) Julian Lloyd ( @julianlloyd )
  25.    Licensed under MIT ( http://www.opensource.org/licenses/mit-license.php )
  26.  
  27. ==============================================================================*/
  28.  
  29. window.scrollReveal = (function( window ){
  30.  
  31.   'use strict';
  32.  
  33.   var _requestAnimFrame;
  34.   var _extend;
  35.   var _handler;
  36.   var self;
  37.  
  38.   function scrollReveal( config ){
  39.  
  40.     self         = this;
  41.     self.elems   = {};
  42.     self.serial  = 1;
  43.     self.blocked = false;
  44.     self.config  = _extend( self.defaults, config );
  45.  
  46.     if ( self.isMobile() && !self.config.mobile || !self.isSupported() ){
  47.       self.destroy();
  48.       return;
  49.     }
  50.  
  51.     if ( self.config.viewport === window.document.documentElement ){
  52.  
  53.       window.addEventListener( 'scroll', _handler, false );
  54.       window.addEventListener( 'resize', _handler, false );
  55.  
  56.     } else {
  57.       self.config.viewport.addEventListener( 'scroll', _handler, false );
  58.     }
  59.  
  60.     self.init( true );
  61.   }
  62.  
  63.   scrollReveal.prototype = {
  64.  
  65.     defaults: {
  66.  
  67.       enter:    'bottom',
  68.       move:     '8px',
  69.       over:     '0.6s',
  70.       wait:     '0s',
  71.       easing:   'ease',
  72.  
  73.       scale:    { direction: 'up', power: '5%' },
  74.       rotate:   { x: 0, y: 0, z: 0 },
  75.  
  76.       opacity:  0,
  77.       mobile:   false,
  78.       reset:    false,
  79.  
  80.       //        Expects a reference to a DOM node (the <html> node by default)
  81.       //        which is used as the context when checking element visibility.
  82.       viewport: window.document.documentElement,
  83.  
  84.       //        'always' — delay every time an animation resets
  85. s
  86.     //        'onload' - delay only for animations triggered by first load
  87. d
  88.     //        'once'   — delay only the first time an animation reveals
  89. als
  90.       delay:    'once',
  91.  
  92.   //        vFactor changes when an element is considered in the viewport.
  93. rt.
  94.   //        The default value of 0.60 means 60% of an element must be
  95.  be
  96.   //        visible for its reveal animation to trigger.
  97. er.
  98.       vFactor:  0.60,
  99.  
  100.       complete: function( el // Note: reset animations do not complete.
  101. te.
  102.     },
  103.  
  104. // Queries the DOM, builds scrollReveal elements and triggers animation.
  105. on.
  106. // @param {boolean} flag — a hook for controlling delay on first load.
  107. load.
  108.     init: function( flag ){
  109.  
  110.       var serial;
  111.       var elem;
  112.       var query;
  113.  
  114.       query = Array.prototype.slice.call( self.config.viewport.querySelectorAll('[data-sr]') );
  115.       query.forEach(function( el ){
  116.  
  117.         serial      = self.serial++;
  118.         elem        = self.elems[ serial ] = { domEl: el };
  119.         elem.config = self.configFactory( elem );
  120.         elem.styles = self.styleFactory( elem );
  121.         elem.seen   = false;
  122.  
  123.         el.removeAttribute('data-sr');
  124.  
  125.         el.setAttribute( ',
  126.            elem.styles.inline
  127.          + elem.styles.initial
  128.        );
  129.      })
  130.  
  131.      self.scrolled = self.scrollY();
  132.      self.animate( flag );
  133.    },
  134.  
  135.    // Applies and removes appropriate styles.
  136.    // @param {boolean} flag — a hook for controlling delay on first load.
  137.    animate: function( flag ){
  138.  
  139.      var key;
  140.      var elem;
  141.      var visible;
  142.  
  143.      // Begin element store digest.
  144.      for ( key in self.elems ){
  145.        if ( self.elems.hasOwnProperty( key ) ){
  146.  
  147.          elem    = self.elems[ key ];
  148.          visible = self.isElemInViewport( elem );
  149.  
  150.          if ( visible ){
  151.  
  152.            if ( self.config.delay === 'ay === 'always'
  153.             || ( self.config.delay === 'onload' && flag )
  154.             || ( self.config.delay === 'once'   && !elem.seen ) ){
  155.  
  156.       // Use delay.
  157.  delay.
  158.               elem.domEl.setAttribute( 'style',
  159.                   elem.styles.inline
  160.                 + elem.styles.target
  161.                 + elem.styles.transition
  162.               );
  163.  
  164.             } else {
  165.  
  166.       // Don’t use delay.
  167. se delay.
  168.               elem.domEl.setAttribute( 'style',
  169.                   elem.styles.inline
  170.                 + elem.styles.target
  171.                 + elem.styles.reset
  172.               );
  173.             }
  174.  
  175.             elem.seen = true;
  176.  
  177.             if ( !elem.config.reset && !elem.animating ){
  178.               elem.animating = true;
  179.               complete( key );
  180.             }
  181.  
  182.           } else if ( !visible && elem.config.reset ){
  183.  
  184.             elem.domEl.setAttribute( 'style',
  185.                 elem.styles.inline
  186.               + elem.styles.initial
  187.               + elem.styles.reset
  188.             );
  189.           }
  190.         }
  191.      // Digest complete, now un-block the event handler.
  192.  handler.
  193.       self.blocked = fals// Cleans the DOM and removes completed elements from self.elems.
  194. lf.ele// @param {integer} key — self.elems property key.
  195. operty key.
  196.       function complete( key ){
  197.  
  198.         var elem = self.elems[ key ];
  199.  
  200.         setTimeout(function(){
  201.  
  202.           elem.domEl.setAttribute( 'style', elem.styles.inline );
  203.           elem.config.complete( elem.domEl );
  204.           delete self.elems[ key ];
  205.  
  206.         }, elem.styles.duration );
  207.       }
  208. // Parses an elements data-sr attribute, and returns a configuration object.
  209. ion // @param {object} elem — An object from self.elems.
  210. m se// @return {object}
  211. turn {object}
  212.     configFactory: function( elem ){
  213.  
  214.       var parsed = {};
  215.       var config = {};
  216.       var words  = elem.domEl.getAttribute('data-sr').split(    wor );
  217.  
  218.       words.forEach(function( keyword, i ){
  219.         switch ( keyword ){
  220.  
  221.           case 'enter':
  222.  
  223.             parsed.enter = words[ i + 1 ];
  224.             break;
  225.  
  226.           case 'wait':
  227.  
  228.             parsed.wait = words[ i + 1 ];
  229.             break;
  230.  
  231.           case 'move':
  232.  
  233.             parsed.move = words[ i + 1 ];
  234.             break;
  235.  
  236.           case 'ease':
  237.  
  238.             parsed.move = words[ i + 1 ];
  239.             parsed.ease = 'ease';
  240.             break;
  241.  
  242.           case 'ease-in':
  243.  
  244.             if ( words[ i + 1 ] == 'up' || words[ i + 1 ] == 'down' ){
  245.  
  246.               parsed.scale.direction = words[ i + 1 ];
  247.               parsed.scale.power     = words[ i + 2 ];
  248.               parsed.easing          = 'ease-in';
  249.               break;
  250.             }
  251.  
  252.             parsed.move   = words[ i + 1 ];
  253.             parsed.easing = 'ease-in';
  254.             break;
  255.  
  256.           case 'ease-in-out':
  257.  
  258.             if ( words[ i + 1 ] == 'up' || words[ i + 1 ] == 'down' ){
  259.  
  260.               parsed.scale.direction = words[ i + 1 ];
  261.               parsed.scale.power     = words[ i + 2 ];
  262.               parsed.easing          = 'ease-in-out';
  263.               break;
  264.             }
  265.  
  266.             parsed.move   = words[ i + 1 ];
  267.             parsed.easing = 'ease-in-out';
  268.             break;
  269.  
  270.           case 'ease-out':
  271.  
  272.             if ( words[ i + 1 ] == 'up' || words[ i + 1 ] == 'down' ){
  273.  
  274.               parsed.scale.direction = words[ i + 1 ];
  275.               parsed.scale.power     = words[ i + 2 ];
  276.               parsed.easing          = 'ease-out';
  277.               break;
  278.             }
  279.  
  280.             parsed.move   = words[ i + 1 ];
  281.             parsed.easing = 'ease-out';
  282.             break;
  283.  
  284.           case 'hustle':
  285.  
  286.             if ( words[ i + 1 ] == 'up' || words[ i + 1 ] == 'down' ){
  287.  
  288.               parsed.scale.direction = words[ i + 1 ];
  289.               parsed.scale.power     = words[ i + 2 ];
  290.               parsed.easing          = 'cubic-bezier( 0.6, 0.2, 0.1, 1 )';
  291.               break;
  292.             }
  293.  
  294.             parsed.move   = words[ i + 1 ];
  295.             parsed.easing = 'cubic-bezier( 0.6, 0.2, 0.1, 1 )';
  296.             break;
  297.  
  298.           case 'over':
  299.  
  300.             parsed.over = words[ i + 1 ];
  301.             break;
  302.  
  303.           case 'flip':
  304.           case 'pitch':
  305.             parsed.rotate   = parsed.rotate || {};
  306.             parsed.rotate.x = words[ i + 1 ];
  307.             break;
  308.  
  309.           case 'spin':
  310.           case 'yaw':
  311.             parsed.rotate   = parsed.rotate || {};
  312.             parsed.rotate.y = words[ i + 1 ];
  313.             break;
  314.  
  315.           case 'roll':
  316.             parsed.rotate   = parsed.rotate || {};
  317.             parsed.rotate.z = words[ i + 1 ];
  318.             break;
  319.  
  320.           case 'reset':
  321.  
  322.             if ( words[ i - 1 ] == 'no' ){
  323.               parsed.reset = false;
  324.             } else {
  325.               parsed.reset = true;
  326.             }
  327.             break;
  328.  
  329.           case 'scale':
  330.  
  331.             parsed.scale = {};
  332.  
  333.             if ( words[ i + 1 ] == 'up' || words[ i + 1 ] == 'down' ){
  334.  
  335.               parsed.scale.direction = words[ i + 1 ];
  336.               parsed.scale.power     = words[ i + 2 ];
  337.               break;
  338.             }
  339.  
  340.             parsed.scale.power = words[ i + 1 ];
  341.             break;
  342.  
  343.           default:
  344.             return;
  345.         }
  346.    // Build default config object, then apply any keywords parsed from the
  347. rsed f// data-sr attribute.
  348. sr attribute.
  349.       config = _extend( config, self.config );
  350.       config = _extend( config, parsed );
  351.  
  352.       if ( config.enter === 'top' || config.enter === 'bottom' ){
  353.         config.axis = 'Y';
  354.       } else if ( config.enter === 'left' || config.enter === 'right' ){
  355.         config.axis = 'X';
  356.       }
  357.  
  358.       if ( config.easing === 'hustle' ){
  359.         config.easing = 'cubic-bezier( 0.6, 0.2, 0.1, 1 )';
  360.  // Let’s make sure our our pixel distances are negative for top and left.
  361. r top // e.g. "enter top and move 25px" starts at 'top: -25px' in CSS.
  362.  -25px' in CSS.
  363.       if ( config.enter === 'top' || config.enter === 'left' ){
  364.         config.move = '-' + config.move;
  365.       }
  366.  
  367.       return conf// Generates styles based on an elements configuration property.
  368. atio// @param {object} elem — An object from self.elems.
  369.  fro// @return {object}
  370.  @return {object}
  371.     styleFactory: function( elem ){
  372.  
  373.       var inline;
  374.       var initial;
  375.       var reset;
  376.       var target;
  377.       var transition;
  378.  
  379.       var cfg      = elem.config;
  380.       var duration = ( parseFloat( cfg.over ) + parseFloat( cfg.wait )// Want to disable delay on mobile devices? Uncomment the line below.
  381. t the // if ( self.isMobile() && self.config.mobile ) cfg.wait = 0;
  382. e ) cfg.wait = 0;
  383.  
  384.       if ( elem.domEl.getAttribute('style') ){
  385.         inline = elem.domEl.getAttribute('style') + '; visibility: visible; ';
  386.       } else {
  387.         inline = 'visibility: visible; ';
  388.       }
  389.  
  390.       transition = '-webkit-transition: -webkit-transform ' + cfg.over + ' ' + cfg.easing + ' ' + cfg.wait + ', opacity ' + cfg.over + ' ' + cfg.easing + ' ' +
  391.                           '                 'transition: transform '         + cfg.over + ' ' + cfg.easing + ' ' + cfg.wait + ', opacity ' + cfg.over + ' ' + cfg.easing + ' ' +
  392.                  '                 '-webkit-perspective: 1000;' +
  393.           '-webkit-backface-visibility: hidden;';
  394.  
  395.       reset      = '-webkit-transition: -webkit-transform ' + cfg.over + ' ' + cfg.easing + ' 0s, opacity ' + cfg.over + ' ' + cfg.easing + ' 0s; ' +
  396.                            'transition: transform '         + cfg.over + ' ' + cfg.easing + ' 0s, opacity ' + cfg.over + ' ' + cfg.easing + ' 0s; ' +
  397.                   '-webkit-perspective: 1000; ' +
  398.           '-webkit-backface-visibility: hidden; ';
  399.  
  400.       initial = 'transform:';
  401.       target  = 'transform:';
  402.     // Build again for webkit…
  403. again for webkit…
  404.       initial += '-webkit-transform:'-webkit-transform:''-webkit-transform:';
  405.       build();
  406.  
  407.       return {
  408.         transition: transition,
  409.         initial:    initial,
  410.         target:     target,
  411.         reset:      reset,
  412.         inline:     inline,
  413.         duration:   durat// Constructs initial and target styles.
  414.  and target styles.
  415.       function build(){
  416.  
  417.         if ( parseInt( cfg.move ) !== 0 ){
  418.           initial += ' translate' + cfg.axis + '(' + cfg.move + ')';
  419.           target  += ' translate' + cfg.axis + '(0)';
  420.         }
  421.  
  422.         if ( parseInt( cfg.scale.power ) !== 0 ){
  423.  
  424.           if ( cfg.scale.direction === 'up' ){
  425.             cfg.scale.value = 1 - ( parseFloat( cfg.scale.power ) * 0.01 );
  426.           } else if ( cfg.scale.direction === 'down' ){
  427.             cfg.scale.value = 1 + ( parseFloat( cfg.scale.power ) * 0.01 );
  428.           }
  429.  
  430.           initial += ' scale(' + cfg.scale.value + ')';
  431.           target  += ' scale(1)';
  432.         }
  433.  
  434.         if ( cfg.rotate.x ){
  435.           initial += ' rotateX(' + cfg.rotate.x + ')';
  436.           target  += ' rotateX(0)';
  437.         }
  438.  
  439.         if ( cfg.rotate.y ){
  440.           initial += ' rotateY(' + cfg.rotate.y + ')';
  441.           target  += ' rotateY(0)';
  442.         }
  443.  
  444.         if ( cfg.rotate.z ){
  445.           initial += ' rotateZ(' + cfg.rotate.z + ')';
  446.           target  += ' rotateZ(0)';
  447.         }
  448.  
  449.         initial += '; opacity: ' + cfg.opacity + '; ';
  450.         target  += '; opacity: 1; ';
  451.       }
  452.     },
  453.  
  454.     getViewportH: function(){
  455.  
  456.       var client = self.config.viewport['clientHeight'];
  457.       var inner  = window['innerHeight'];
  458.  
  459.       if ( self.config.viewport === window.document.documentElement ){
  460.         return ( client < inner ) ? inner : client;
  461.       }
  462.  
  463.       return client;
  464.     },
  465.  
  466.     scrollY: function(){
  467.       if ( self.config.viewport === window.document.documentElement ){
  468.         return window.pageYOffset;
  469.       } else {
  470.         return self.config.viewport.scrollTop + self.config.viewport.offsetTop;
  471.       }
  472.     },
  473.  
  474.     getOffset: function( el ){
  475.  
  476.       var offsetTop  = 0;
  477.       var offsetLeft = 0;
  478.  
  479.       do {
  480.         if ( !isNaN( el.offsetTop ) ){
  481.           offsetTop  += el.offsetTop;
  482.         }
  483.         if ( !isNaN( el.offsetLeft ) ){
  484.           offsetLeft += el.offsetLeft;
  485.         }
  486.       } while ( el = el.offsetParent );
  487.  
  488.       return {
  489.         top: offsetTop,
  490.         left: offsetLeft
  491.       };
  492.     },
  493.  
  494.     isElemInViewport: function( elem ){
  495.  
  496.       var elHeight = elem.domEl.offsetHeight;
  497.       var elTop    = self.getOffset( elem.domEl ).top;
  498.       var elBottom = elTop + elHeight;
  499.       var vFactor  = elem.config.vFactor || 0;
  500.  
  501.       return ( confirmBounds() || isPositionFixed() );
  502.  
  503.       function confirmBounds(){
  504.  
  505.         var top        = elTop + elHeight * vFactor;
  506.         var bottom     = elBottom - elHeight * vFactor;
  507.         var viewBottom = self.scrolled + self.getViewportH();
  508.         var viewTop    = self.scrolled;
  509.  
  510.         return ( top < viewBottom ) && ( bottom > viewTop );
  511.       }
  512.  
  513.       function isPositionFixed(){
  514.  
  515.         var el    = elem.domEl;
  516.         var style = el.currentStyle || window.getComputedStyle( el, null );
  517.  
  518.         return style.position === 'fixed';
  519.       }
  520.     },
  521.  
  522.     isMobile: function(){
  523.  
  524.       var agent = navigator.userAgent || navigator.vendor || window.opera;
  525.  
  526.       return (|android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test( agent )||/120.test( agent )||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test( agent.substr( 0, 4 ))) ? true : false;
  527.     },
  528.  
  529.     isSupported: function(){
  530.  
  531.       var sensor    = document.createElement('sensor');
  532.       var cssPrefix = 'Webkit,Moz,O,'.split(',');
  533.       var tests     = ( 'transition ' + cssPrefix.join('transition,') ).split(',');
  534.  
  535.       for ( var i = 0; i < tests.length; i++ ){
  536.         if ( !sensor.style[tests[i]] === '' ){
  537.           return false;
  538.         }
  539.       }
  540.  
  541.       return true;
  542.     },
  543.  
  544.     destroy: function(){
  545.  
  546.       var node = self.config.viewport;
  547.       var query = Array.prototype.slice.call( node.querySelectorAll('[data-sr]') );
  548.  
  549.       query.forEach(function( el ){
  550.         el.removeAttribute('data-sr');
  551. // End of the scrollReveal prototype ======================================|
  552. ==================|
  553.  
  554.   _handler = function( e ){
  555.  
  556.     if ( !self.blocked ){
  557.  
  558.       self.blocked  = true;
  559.       self.scrolled = self.scrollY();
  560.  
  561.       _requestAnimFrame(function(){
  562.         self.animate();
  563.       });
  564.     }
  565.   }
  566.  
  567.   _extend = function( target, src ){
  568.  
  569.     for ( var prop in src ){
  570.       if ( src.hasOwnProperty( prop ) ){
  571.         target[ prop ] = src[ prop ];
  572.       }
  573.     }
  574.  
  575.     re// RequestAnimationFrame polyfill.
  576. tionFrame polyfill.
  577.   _requestAnimFrame = (function(){
  578.  
  579.     return window.requestAnimationFrame        ||
  580.            window.webkitRequestAnimationFrame  ||
  581.            window.mozRequestAnimationFrame     ||
  582.  
  583.           function( callback ){
  584.             window.setTimeout( callback, 1000 / 60 );
  585.           };
  586.   }());
  587.  
  588.   return scrollReveal;
  589.  
  590. })( window );
  591.  
  592. return

Raw Paste


Login or Register to edit or fork this paste. It's free.