How to reset CSS transition once it played

I have a plus sign that appears if you push the space button. But now it appears once. Can you help me to make it appear every time I press the space button? Here is my Code Pen.

import './style.scss';

let counter = 0;

document.addEventListener('keydown', ({ keyCode }) => {
  const increment = document.getElementsByClassName('increment')[0];
  if (keyCode === 32) {
    counter++;
    document.getElementsByClassName('counter')[0].innerText = counter;

    increment.classList.remove('hidden');
    increment.classList.add('move-increment');
  }
});
.container {
   /* ... */

  .counter {
    background-color: gray;
    color: white;
    border-radius: 10px;
    padding: 10px;
  }

  .move-increment {
    margin-top: -20px;
    opacity: 0;
  }

  .hidden {
    visibility: hidden;
  }

  .increment {
    position: absolute;
    margin-left: -33px;
    z-index: 1;
    transition: margin-top 1s cubic-bezier(0, 0.5, 0.5, 1),
      opacity 1s ease-in-out;
  }
}

Upvotes: 8

Views: 520

Answers (3)

Abolfazl Panbehkar
Abolfazl Panbehkar

Reputation: 708

I think you don't need to hidden class, Simply you can use setTimeout for reset class, like this:

let counter = 0;

document.addEventListener("keydown", ({ keyCode }) => {
  const increment = document.getElementsByClassName("increment")[0];
  if (keyCode === 32) {
    counter++;
    document.getElementsByClassName("counter")[0].innerText = counter;
    increment.classList.add("move-increment");
    setTimeout(function () {
      increment.classList.remove("move-increment");
    }, 1000);
  }
});
.container {
     font-family: Arial, Helvetica, sans-serif;
     font-size: 40px;
     font-weight: bold;
     display: flex;
     height: 500px;
     align-items: center;
     justify-content: center;
}
 .container .counter {
     background-color: gray;
     color: white;
     border-radius: 10px;
     padding: 10px;
}
 .container .increment {
     position: absolute;
     margin-left: -33px;
     z-index: 1;
     visibility: hidden;
     margin-top: 0;
     opacity: 1;
     transition: margin-top 1s cubic-bezier(0, 0.5, 0.5, 1), opacity 1s ease-in-out;
}
 .container .increment.move-increment {
     visibility: visible;
     margin-top: -20px;
     opacity: 0;
}
 
 <div class="container">
   <div>
     Counter: <span class="counter">0</span>
     <span class="increment">+</span>
   </div>
 </div>

Upvotes: 1

ikiK
ikiK

Reputation: 6532

Remove added .move-increment and add again removed hidden classes with slight delay, this will re-apply your transition: margin-top (read in provided links why delay):

    setTimeout(function() {increment.classList.add('hidden');
    increment.classList.remove('move-increment');}, 600);   

Solution (changed key-code to arrow up: ↑ ):

let counter = 0;

document.addEventListener('keydown', ({
    keyCode
  }) =>

  {
    const increment = document.getElementsByClassName('increment')[0];
    if (keyCode === 38) {
      counter++;
      document.getElementsByClassName('counter')[0].innerText = counter;

      increment.classList.remove('hidden');
      increment.classList.add('move-increment');

      setTimeout(function() {
        increment.classList.add('hidden');
        increment.classList.remove('move-increment');
      }, 600);
    }
  });
.container {
  font-family: Arial, Helvetica, sans-serif;
  font-size: 40px;
  font-weight: bold;
  display: flex;
  height: 100px;
  align-items: center;
  justify-content: center;
}

.counter {
  background-color: gray;
  color: white;
  border-radius: 10px;
  padding: 10px;
}

.move-increment {
  margin-top: -20px;
  opacity: 0;
}

.hidden {
  visibility: hidden;
}

.increment {
  position: absolute;
  margin-left: -33px;
  z-index: 1;
  transition: margin-top 1s cubic-bezier(0, 0.5, 0.5, 1), opacity 1s ease-in-out;
}
<div class="container">
  <div>
    Counter: <span class="counter">0</span>
    <span class="increment hidden">+</span>
  </div>
</div>

But however, this is not working perfectly when pressing key too fast. Try changing setTimeout duration and see what suits your need.

In links provided you have examples how to reset animation (not transition) all together and would solve this fast key press issues.

Read about this here, few really useful info's:

Restart CSS Animation

Controlling CSS Animations and Transitions with JavaScript

Upvotes: 2

Terminator-Barbapapa
Terminator-Barbapapa

Reputation: 3126

Although I consider @ikiK's answer as the correct answer because the question was specifically about using CSS transitions, I would like to share a different approach. I think the goal of the 'plus' icon is to be displayed each time the counter increments. But when the counter increments while the transition of the previous increment is still playing it is impossible to display a second 'plus' symbol.

My suggestion would be to use some jQuery and, on each increment, append a new li item to an unordered list that is positioned right on top of the counter. Animate that li, fading it out to the top. And then use the callback function of animate() to remove the li element from the DOM once it has faded out of view.

let counter = 1;
$(document).on( 'keypress',function(e) {
    if( e.which == 32 ) {
        $('.counter').text(counter++);
        let increment = $('<li><span class="increment">+</span></li>');
        $('#increments').append(increment);
        increment.animate({
            opacity: 0,
            top: '-=30px'
        }, 500, function() {
            increment.remove();
        });
    }
});
.container {
    font-family: Arial, Helvetica, sans-serif;
    font-size: 40px;
    font-weight: bold;
    display: flex;
    height: 500px;
    align-items: top;
    justify-content: center;
    position: relative;
  overflow: hidden;
  height: 100px;
}

.counter {
    background-color: gray;
    color: white;
    border-radius: 10px;
    padding: 10px;
}

#increments {
    padding: 0px;
    z-index: 1;
    float: left;
    margin-left: -33px;
    list-style: none;
}

#increments li {
    position: absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
    <p>Counter: <span class="counter">0</span></p>
    <ul id="increments"></ul>
</div>

Upvotes: 4

Related Questions