JSFiddle - React, Tailwind, and code Playground

by _sir

HTML

<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
      crossorigin="anonymous"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="js/jquery.pause.min.js"></script>

<div class="row">
  <div class="col-5 musicVisualizer">
    <div class="bar bar1"></div>
    <div class="bar bar2"></div>
    <div class="bar bar3"></div>
    <div class="bar bar4"></div>
    <div class="bar bar5"></div>
		<i class="fa fa-sort-desc fa-lg"></i>
  </div>
</div>

CSS

.musicVisualizer {
  margin-top: 28.5em;
  width: 200px;
  height: 200px; }

.bar {
  background-color: #444;
  width: 1rem;
  position: fixed;
  box-shadow: inset 0px -6px 0px 0px #5baac7; }

.bar1 {
  height: 3rem;
  background-repeat: no-repeat;
  background-size: contain; }

.bar2 {
  margin-left: 1.3rem;
  height: 4rem;
  background-repeat: no-repeat;
  background-size: contain; }

.bar3 {
  margin-left: 2.6rem;
  height: 5rem;
  background-repeat: no-repeat;
  background-size: contain; }

.bar4 {
  margin-left: 3.9rem;
  height: 3rem;
  background-repeat: no-repeat;
  background-size: contain; }

.bar5 {
  margin-left: 5.2rem;
  height: 2rem;
  background-repeat: no-repeat;
  background-size: contain; }

JavaScript

var continueCycle = true;

$(document).ready(function(){
        $('.musicVisualizer').one('click', function() {
        	$('.bar').stop();
          continueCycle = false;
          function barMorph() {
            $('.bar').animate({height: '5px'}, 'easeInCubic', function() {
              $('.fa-caret-right').hide();
            });
            $('.bar1').animate({'width': '5px'});
            $('.bar2').animate({'marginTop': "+=20px", 'marginLeft': '-=21px', 'width': '5px'
            }, 600);
            $('.bar3').animate({'marginTop': "+=40px", 'marginLeft': '-=42px', 'width': '5px'}, 600);
            $('.bar4').animate({'marginTop': "+=60px", 'marginLeft': '-=62px', 'width': '5px'}, 600);
            $('.bar5').animate({'marginTop': "+=80px", 'marginLeft': '-=83px', 'width': '5px'}, 600);
          }
          barMorph();
        });
      });


// Call this to make a function used in the promise chain
function jqAnimatePromise($el, props, duration, easing) {
	// We could just use bind, but the point is we need to make a function
  //  that will be called when the promise resolves;
	return function() {
  if (continueCycle === false) { 
  	return false;
  }
  	// This needs to return so we pass on the next promise.
  	return $el.animate(props, duration, easing).promise();
  }
}
function bar1Animate() {
  var $bar1 = $('.bar1');
  // As our function returns a function, we have to kick it off
  // Which is why there are an "extra" pair of parentheses
  jqAnimatePromise($bar1, {height: '2rem'}, 180, 'linear')()
    .then(jqAnimatePromise($bar1, {height: '5rem'}, 270, 'linear'))
    .then(jqAnimatePromise($bar1, {height: '1rem'}, 360, 'linear'))
    .then(jqAnimatePromise($bar1, {height: '3rem'}, 180, 'linear'))
    .then(function() {
    	if (continueCycle) {
      	bar1Animate();
      }
    });
}

// I've split up the functions so that eash bar has its own process.

// Because we know there are certain repetitions, we can simplify
function...