javascriptweb-animationsweb-animations-api

Compounding Value within an object used to slide dot across the page incrementally


I am unable to get a variable to function properly as the translateX value within my object. I am wanting to make the dot scroll across the page each time the next button is clicked. My code is only able to move it back and forth for the first step.

I am new to the animation API, and I have already made this work with CSS transitions but I am trying to get a good handle on the API.

html:

<div class="progress__container">

                <div class="progress__bar">
                        <div id="progress__fill" class="step1"></div>
                        <div class="circ" id="circ__1"></div>
                        <div class="circ" id="circ__2"></div>
                        <div class="circ" id="circ__3"></div>
                        <div class="circ" id="circ__4"></div>



                        <div id="progress__dot" class="prog__1"></div>
                    </div>
            <div class="backBar"></div>
            <div class="flexrow">
                    <span class="stepName">Account</span>
                    <span class="stepName">Frequency</span>
                    <span class="stepName">Amount</span>
                    <span class="stepName">Taxes</span>
                </div>
            <div class="button__container">
                <button class="buttonStep" id="back">Back</button>
                <button class="buttonStep is-active" id="next">Next</button>
            </div>
    </div>

js:

// give a starting value for the transformation
var startVal = 0;

// define the keyframes
var moveDot = [
    { transform: `translateX(${startVal}px)`},
    { transform: `translateX(${startVal + 190}px)`}
  ];

// definte the timing
var dotTiming = {
    duration: 400,
      fill: "forwards",
      easing: 'ease-in',
} 

// make the animation happen
var movingDot = document.getElementById("progress__dot").animate(
    moveDot,
    dotTiming
  );
//  pause the animation until called
movingDot.pause();





    // on click fire the animation
document.getElementById('next').addEventListener('click', function() {
    movingDot.playbackRate = 1;

    if (startVal <= 380) {
        movingDot.play();
        startVal += 190;
    } 



});


document.getElementById('back').addEventListener('click', function() {
    movingDot.playbackRate = -1;
    if (startVal >= 0) {
        movingDot.play();
        startVal -= 190;
    } 

});

css:

#progress__fill {
    height:2px;
    position: absolute;
    top: 7px;
    left: 0;
    background-color: darkred;
}
#progress__dot {
    background-color: darkred;
    color: #fff;
    border-radius: 50%;
    height: 8px;
    width: 8px;
    position: absolute;
    text-align:center;
    line-height: 8px;
    padding: 6px;
    top: 0;
    font-size: 12px;


}





/* Static Bar Elements */
.progress__container {
 width: 600px;
 margin: 20px auto;
 position: relative;

}
.backBar {
    height:2px;
    width:96%;
    position: absolute;
    top: 7px;
    left: 2%;
    background-color: lightgrey;
}
.progress__bar {
    z-index: 100;
    position: relative;
    width: 96%;
    margin: 0 auto;
}
.circ {
    background-color: #fff;
    border: 2px solid lightgrey;
    border-radius: 50%;
    height: 12px;
    width: 12px;
    display: inline-block;

}
#circ__2, #circ__3 {
    margin-left: 30%
}
#circ__4 {
    float: right;
}
.passed {
    background-color: darkred;
    border: 2px solid darkred;
}
.hide {
    visibility: hidden
}
.flexrow {
    display: flex;
    flex-direction: row;
    justify-content: space-between;
}


/* Buttons */
.buttonStep {
    background: grey;
    color: #fff;
    padding: 10px 25px;
    border-radius: 10px;
    font-size: 16px;
}
#back {
    float: left;
}
#next {
    float: right;
}
.is-active {
    background: darkred;
}

The way I have it set up, I expect for the translateX values to increment or decrement depending on the click event listeners which would make the circle slide across the page. What is actually happening is that only the first step works. it will not go past the first stop point. If I log moveDot in the console it gives me the values that I am expecting, but it will only start/stop at 0 and 190. the back button functions the same way. link to fiddle


Solution

  • It is animated from and to the same place every time. Move the definition of moveDot into the event listener:

    // give a starting value for the transformation
    var startVal = 0;
    
    // definte the timing
    var dotTiming = {
      duration: 400,
      fill: "forwards",
      easing: 'ease-in',
    }
    
    // on click fire the animation
    document.getElementById('next').addEventListener('click', function() {
      if (startVal > 380){return;}
    
      // define the keyframes
      var moveDot = [{transform: `translateX(${startVal}px)`},
        {transform: `translateX(${startVal + 190}px)`}];
    
      // make the animation happen
      var movingDot = document.getElementById("progress__dot").animate(
        moveDot,
        dotTiming
      );
    
      movingDot.playbackRate = 1;
    
    
      movingDot.play();
      startVal += 190;
    
    
    
    });
    
    
    document.getElementById('back').addEventListener('click', function() {
      movingDot.playbackRate = -1;
      if (startVal >= 0) {
        movingDot.play();
        startVal -= 190;
      }
    
    });