animated level transition - stripes

using angular 1, jquery, lodash; fully responsive; customizable

by Ercan Cicek

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>
<body ng-app="transitApp" ng-controller="transitCtrl">

  <div class="stripe-anim-parent">
    <div class="stripe-anim-txt-cont flex-it">
      <span>Good Job!</span>
      <span>Level Unlocked!</span>
    </div>
    <div id="stripe-{{i}}" class="stripe-anim-stripe" ng-class="$even ? 'stripe-anim-even' : 'stripe-anim-odd'" ng-style="{ top: ($index * (100 / 8)) + '%'}" ng-repeat="i in [0,1,2,3,4,5,6,7]"></div>
  </div>
  
</body>

SCSS

/* --- vars --- */
$stripeCol1: #00A69C; /* --- customizable hex or string --- */
$stripeCol2: #16D8C5; /* --- customizable hex or string --- */
$txtCol: white; /* --- customizable hex or string --- */
$txtSize: 1.5em; /* --- customizable em or pt --- */

html, body {
  position: relative;
  width: 100%;
  height: 100%;
}

.stripe-anim-txt-cont {
  position: absolute;
  top: -100%;
  left: 0;
  width: 100%;
  height: 100%;
  background: $stripeCol1;
  z-index: 16777271; /* max z-index (for Safari 1-3) - overlaps everything */
  color: $txtCol;
  font-size: $txtSize;
}

.stripe-anim-parent {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  z-index: 16777270; /* max z-index (for Safari 1-3) - 1 */
}

.stripe-anim-stripe {
  position: absolute;
  width: 120%;
  height: calc(100% / 8);
  border-radius: 65px;
}

.stripe-anim-odd {
  background: $stripeCol1;
  left: 100%;
}

.stripe-anim-even {
  background: $stripeCol2;
  left: -120%;
}

.flex-it {
  display: -webkit-box;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;     
  align-items: center;
  justify-content: center;
  flex-direction: column;
}

JavaScript

var app = angular.module('transitApp', []).controller('transitCtrl', [function() {

  var startAnimTime = 2000,
  		stayAnimTime = 1000,
      endAnimTime = 2000,
      delayBtwStripes = 1000;
  // --- fully customizable
  // --- animation time is always relevant animTime + delayBtwStripes

  $(animationStart);
  function animationStart() {
    $(".stripe-anim-stripe").each(function(index) {
      var self = this;
      setTimeout(function() {
        $(self).animate({left: "-10%"}, startAnimTime, function() { waitSeq(index); });
        // --- if next to last stripe animation starts (8 stripes) -> start animation of txt cont
        if(index === 6) { moveTxtCont(true); }
      }, index * (delayBtwStripes / 7));
    });
  }
  
  function waitSeq(index) {
  // --- if last stripe finished -> trigger endAnimation
  	if(index === 7) {
    	setTimeout(animationEnd, stayAnimTime);
    }
  }

  function animationEnd(callback) {
  // --- start animation of txt cont immediately
    moveTxtCont(false);
    _.reverse($(".stripe-anim-stripe")).each(function(index) {
      var self = this;
      setTimeout(function() {
        $(self).animate({left: index % 2 === 0 ? "-120%" : "100%"}, endAnimTime);
      }, index * (delayBtwStripes / 7));
    });
  }

  function moveTxtCont(shw) {
    $(".stripe-anim-txt-cont").animate({top: shw ? "0" : "-100%"}, shw ? (startAnimTime + (delayBtwStripes/7)) : endAnimTime + delayBtwStripes);
  }

}]);