Search code examples
javascriptjqueryhtmlcssgsap

Reverse the CSS animation using jQuery


Here is a code that animates a progress bar using the CSS keyframe. Now the problem is what if we want to reverse the animation at some point in the middle of the CSS animation?

I mean at second 4 while CSS animation is working I want to suddenly pause it and reverse the animation and animate the bar to the very beginning.

Here is what I have tried...

I think it's possible and I'm missing something cause the reverse animation doesn't affect the bar at all and is kind of wired!

Note: Any kind of solution (like TweenMax) is accepted ...

//first of all pause the animation
pauseUsingCSS();
console.log("pauseUsingCSS executed!");

//after 2 seconds play it
setTimeout(function(){   
   playUsingCSS();
}, 2000)

//Two seconds later reverse the animation to where it started using JQuery
setTimeout(function(){       
   reverseUsingJquery()
}, 4000)


function reverseUsingJquery(){
    // Here Is Where The Problem Exist...
    pauseUsingCSS(); // pause the animation first
    $('#progress-bar').animate({width: 0, marginLeft: 0}, {duration: 1000});
    console.log("reverseUsingJquery initiated!");
    
}

function pauseUsingCSS(){
   document.getElementById("progress-bar").classList.add("paused");  
}

function playUsingCSS(){
   document.getElementById("progress-bar").classList.add("played");
   console.log("playUsingCSS executed!");
}
#progress-bar {
  position: absolute;
  border: 0vh solid rgba(0, 0, 0, 0.8);
  width: 0vw;
  height: 9.436435124508519vh;
  margin: 62.909567496723468vh 0vw 0vh  11.2119791666666659491vw;
  background: repeating-linear-gradient(-45deg, red, red 2.80299479166666659491vw, orangered 2.80299479166666659491vw, orangered 5.60598958333333297455vw);
  border-radius: 18vh;
  animation: roll 10s linear forwards;
  box-shadow: inset 0vw 7.8636959370904332vh 1.40149739583333318982vw rgba(255, 255, 255, 0.2), inset 0vw 0.7863695937090432vh 0vw rgba(255, 255, 255, 0.3), inset 0vw -3.9318479685452166vh 0.42044921875vw rgba(0, 0, 0, 0.2), 0vw 2.3591087811271296vh 0.280299479166666681018vw rgba(0, 0, 0, 0.3);
  left: -0.70074869791666659491vw;
  top: -3.9vh;
}

#progress-bar:after {
  position: absolute;
  width: 28.0299479166666681018vw;
  height: 15.7273918741808664vh;
  border: 0.140149739583333340509vw solid rgba(13, 13, 13, 0.7);
  background: rgba(13, 13, 13, 0.7);
  border-radius: 18vh;
  content: "";  
  left: -0.70074869791666659491vw;
  top: -3.9vh;
  z-index: -1;
}

@-webkit-keyframes roll {
  0% {
    width: 1vw;
  }
  100% {
    width: 26.6284505208333318982vw;
  }
}


.paused {
   -webkit-animation-play-state: paused !important; 
}

.played {
   -webkit-animation-play-state: running !important; 
}
<script
  src="https://code.jquery.com/jquery-3.4.1.js"
  integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU="
  crossorigin="anonymous"></script>

  
<div id="progress-bar"></div>

  <link rel="stylesheet" type="text/css" href="style.css">

<script src="script.js"></script>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.1.3/TweenMax.min.js"></script>


Solution

  • So what i have done below is create a keyframe called roll-back based off the current width of the element and insert it into the head of the site. Then on reverse i add an inline animation style of roll-back which does the trick. This was as well you can control the flow of the reverse animation as you can customise the timings etc.

    I also created a function to allow you to reset the dynamic changes so that it can be resumed going forwards easily.

    //first of all pause the animation
    pauseUsingCSS();
    //console.log("pauseUsingCSS executed!");
    
    //after 2 seconds play it
    setTimeout(function(){   
       playUsingCSS();
    }, 2000)
    
    //Two seconds later reverse the animation to where it started using JQuery
    setTimeout(function(){       
       reverseUsingJquery()
    }, 4000)
    
    
    function reverseUsingJquery(){
        // Here Is Where The Problem Exist...
        pauseUsingCSS(); // pause the animation first
        let progress = $('#progress-bar');
        
        var css = `
            @-webkit-keyframes roll-back {
              0% {
                width: ${progress.width()}px;
              }
              100% {
                width: 1vw;
              }
            }
        `,
        head = document.head,
        style = document.createElement('style');
        style.id = 'rollback';
        head.appendChild(style);
        
        progress.css('animation', 'roll-back 10s linear forwards');
    
        style.type = 'text/css';
        if (style.styleSheet){
          style.styleSheet.cssText = css;
        } else {
          style.appendChild(document.createTextNode(css));
        }
        
        playUsingCSS();
        //console.log("reverseUsingJquery initiated!");
    }
    
    function resetBarStyles(){
        $('#progress-bar').attr('style', '');
        $('#rollback').remove();
    }
    
    function pauseUsingCSS(){
       document.getElementById("progress-bar").classList.add("paused");  
    }
    
    function playUsingCSS(){
       document.getElementById("progress-bar").classList.add("played");
       //console.log("playUsingCSS executed!");
    }
    #progress-bar {
      position: absolute;
      border: 0vh solid rgba(0, 0, 0, 0.8);
      width: 0vw;
      height: 9.436435124508519vh;
      margin: 62.909567496723468vh 0vw 0vh  11.2119791666666659491vw;
      background: repeating-linear-gradient(-45deg, red, red 2.80299479166666659491vw, orangered 2.80299479166666659491vw, orangered 5.60598958333333297455vw);
      border-radius: 18vh;
      animation: roll 10s linear forwards;
      box-shadow: inset 0vw 7.8636959370904332vh 1.40149739583333318982vw rgba(255, 255, 255, 0.2), inset 0vw 0.7863695937090432vh 0vw rgba(255, 255, 255, 0.3), inset 0vw -3.9318479685452166vh 0.42044921875vw rgba(0, 0, 0, 0.2), 0vw 2.3591087811271296vh 0.280299479166666681018vw rgba(0, 0, 0, 0.3);
      left: -0.70074869791666659491vw;
      top: -3.9vh;
    }
    
    #progress-bar:after {
      position: absolute;
      width: 28.0299479166666681018vw;
      height: 15.7273918741808664vh;
      border: 0.140149739583333340509vw solid rgba(13, 13, 13, 0.7);
      background: rgba(13, 13, 13, 0.7);
      border-radius: 18vh;
      content: "";  
      left: -0.70074869791666659491vw;
      top: -3.9vh;
      z-index: -1;
    }
    
    @-webkit-keyframes roll {
      0% {
        width: 1vw;
      }
      100% {
        width: 26.6284505208333318982vw;
      }
    }
    
    
    .paused {
       -webkit-animation-play-state: paused !important; 
    }
    
    .played {
       -webkit-animation-play-state: running !important; 
    }
    <script
      src="https://code.jquery.com/jquery-3.4.1.js"
      integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU="
      crossorigin="anonymous"></script>
    
      
    <div id="progress-bar"></div>
    
      <link rel="stylesheet" type="text/css" href="style.css">
    
    <script src="script.js"></script>
    
      <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.1.3/TweenMax.min.js"></script>