Home  >  Q&A  >  body text

How to make animation pause on hover but continue once mouse leaves

I've tired of several solutions and this is the closest I've gotten. But I'm still not happy with how it turned out, because when the mouse leaves the element, the element reverts to its original rotation. The idea is that if you go over the element, it will trigger the animation even if the mouse leaves the element. If you hover over the element, it will animate and stay at 0 degrees, and once the mouse leaves, another animation will play and rotate back to -8 degrees.

const elements = document.getElementsByClassName('rotate_left');

for (let i = 0; i <= elements.length; i++) {
  elements[i].addEventListener('animationend', function(e) {
    elements[i].classList.remove('animated')
    /*elements[i].classList.add('animatedback')*/
  });

  elements[i].addEventListener('mouseover', function(e) {
    elements[i].classList.add('animated')
    elements[i].classList.remove('animatedback')
  });
}
.rotate_left {
  -ms-transform: rotate(-8deg);
  -webkit-transform: rotate(-8deg);
  transform: rotate(-8deg);
  transition-duration: 1s;
  transition-delay: 0.25s;
}

.polaroid {
  width: 280px;
  height: 200px;
  padding: 10px 15px 100px 15px;
  border: 1px solid #BFBFBF;
  border-radius: 2%;
  background-color: white;
  box-shadow: 10px 10px 5px #aaaaaa;
}

.polaroid:hover {
  width: 280px;
  height: 200px;
  padding: 10px 15px -100px 15px;
  border: 1px solid #BFBFBF;
  border-radius: 2%;
  background-color: white;
  box-shadow: 10px 10px 5px #aaaaaa;
  -ms-transform: rotate(0deg);
  -webkit-transform: rotate(0deg);
  transform: rotate(0deg);
  transition-duration: 1s;
  transition-delay: 0.25s;
}

@keyframes animationBegining {
  from {
    -ms-transform: rotate(-8deg);
    /* IE 9 */
    -webkit-transform: rotate(-8deg);
    /* Safari */
    transform: rotate(-8deg);
  }
  to {
    -ms-transform: rotate(0deg);
    /* IE 9 */
    -webkit-transform: rotate(0deg);
    /* Safari */
    transform: rotate(0deg);
  }
}

@keyframes animatedBack {
  form {
    -ms-transform: rotate(0deg);
    /* IE 9 */
    -webkit-transform: rotate(0deg);
    /* Safari */
    transform: rotate(0deg);
  }
  to {
    -ms-transform: rotate(-8deg);
    /* IE 9 */
    -webkit-transform: rotate(-8deg);
    /* Safari */
    transform: rotate(-8deg);
  }
}

.animatedback {
  animation: animatedBack 2s;
}

.animated {
  animation: animationBegining 2s;
}
<div id="modalWrepper1" class="polaroid rotate_left">
  <p class="caption">Just a basic explanation of the picture.</p>
</div>

Thank you for your help.

Once the mouse leaves the element, there is a smooth animation back to the original rotation.

P粉786800174P粉786800174181 days ago358

reply all(1)I'll reply

  • P粉322319601

    P粉3223196012024-04-02 00:03:49

    Pure CSS solution (second animation needs to be prevented)

    You don’t need JS or any fancy classes. transform and transition-duration will do.

    Let's start with the HTML; this is still your code, but simplified:

    Just a basic explanation of the picture.

    Now, the main part: CSS. Since your card is rotated by -8 degrees by default, we've added a rule to do this:

    .rotate_left {
      transform: rotate(-8deg);
      transition-duration: 1s;
      transition-delay: 0.25s;
    }
    

    If you hover . Polaroid over it, it will rotate back to 0 degrees. This means we can use the pseudo class :hover:

    .polaroid:hover {
      transform: rotate(0deg);
    }
    

    Once you move the mouse away from .poloid, the :hover rules no longer apply. This means it will revert to the previous rule within 1 second, starting 0.25 seconds after the mouse is gone.

    try it:

    .rotate_left {
      transform: rotate(-8deg);
      transition-duration: 1s;
      transition-delay: 0.25s;
    }
    
    .polaroid:hover {
      transform: rotate(0deg);
    }
    
    /* Demo only */
    
    .polaroid {
      border: 1px solid #bfbfbf;
      border-radius: 2%;
      padding: 10px 15px;
      height: 200px;
      width: 280px;
      box-shadow: 10px 10px 5px #aaa;
    }

    Just a basic explanation of the picture.

    Prevent the second animation from stopping

    To prevent recovery from stalling, some JS is required.

    First, we declare some constants:

    const card = document.querySelector('.rotate_left');
    
    const duration = 1000; // Duration of animation, in milliseconds.
    const delay = 250; // Delay before animation, in milliseconds.
    
    const keyframes = [
      { transform: 'rotate(-8deg)' },
      { transform: 'rotate(0deg)' },
    ];
    const options = {
      duration, delay,
      fill: 'forwards'
    };
    

    Then we create a handler:

    const handler = () => {
      // New mouse over & leave should not mess with current animation.
      if (card.classList.contains('rotating')) {
        return;
      }
      
      // Let ourselves know that an animation is playing.
      card.classList.add('rotating');
      
      let animation;
      
      if (card.classList.contains('not_rotated')) {
        // Rotated to 0 degree, reverting.
        animation = card.animate([...keyframes].reverse(), options);
      } else {
        animation = card.animate(keyframes, options);
      }
      
      // Make sure we clean after ourselves after animation.
      animation.finished.then(() => {
        card.classList.remove('rotating');
        card.classList.toggle('not_rotated');
      });
    };
    

    Add this as an event handler for 'mouseover'/'mouseleave' and we're done:

    card.addEventListener('mouseover', handler);
    card.addEventListener('mouseleave', handler);
    

    try it:

    const card = document.querySelector('.rotate_left');
    
    const duration = 1000; // Duration of animation, in milliseconds.
    const delay = 250; // Delay before animation, in milliseconds.
    
    const keyframes = [
      { transform: 'rotate(-8deg)' },
      { transform: 'rotate(0deg)' },
    ];
    const options = {
      duration, delay,
      fill: 'forwards'
    };
    
    const handler = () => {
      if (card.classList.contains('rotating')) {
        return;
      }
      
      card.classList.add('rotating');
      
      let animation;
      
      if (card.classList.contains('not_rotated')) {
        animation = card.animate([...keyframes].reverse(), options);
      } else {
        animation = card.animate(keyframes, options);
      }
      
      animation.finished.then(() => {
        card.classList.remove('rotating');
        card.classList.toggle('not_rotated');
      });
    };
    
    card.addEventListener('mouseover', handler);
    card.addEventListener('mouseleave', handler);
    .rotate_left {
      transform: rotate(-8deg);
    }
    
    /* Demo only */
    
    .polaroid {
      border: 1px solid #bfbfbf;
      border-radius: 2%;
      padding: 10px 15px;
      height: 200px;
      width: 280px;
      box-shadow: 10px 10px 5px #aaa;
    }

    Just a basic explanation of the picture.

    reply
    0
  • Cancelreply