Обратная анимация не применяется должным образом для события мыши

1

Я пытаюсь применить анимацию на событии mouseover (отлично работает) и ту же анимацию с reverse и backwards свойствами, чтобы воспроизвести ее на mouseleave. Но вторая часть работает неправильно. Наконец, я хочу, чтобы анимация играла вперед по mouseover и назад на mouseleave. И если есть способ применить следующую анимацию с этой точки, где предыдущий был остановлен, включите его в свой ответ. Вот мой код:

const target = document.getElementById("animated");
target.addEventListener("mouseover", animateForward);
target.addEventListener("mouseout", animateBackward);

function animateForward() {
  target.style.animation = 'custom 1.6s forwards';
}

function animateBackward() {
  target.style.animation = 'custom 1.6s reverse backwards';
}
/* Safari 4.0 - 8.0 */
@-webkit-keyframes custom {
    25% {
      border-radius: 50% 0 0 0;
    }
    
    50% {
      border-radius: 50% 50% 0 0;
    }
    
    75% {
      border-radius: 50% 50% 50% 0;
    }
    
    100% {
      border-radius: 50% 50% 50% 50%;
      background-color: violet;
    }
} 

/* Standard syntax */ 
@keyframes custom {
    25% {
      border-radius: 50% 0 0 0;
    }
    
    50% {
      border-radius: 50% 50% 0 0;
    }
    
    75% {
      border-radius: 50% 50% 50% 0;
    }
    
    100% {
      border-radius: 50% 50% 50% 50%;
      background-color: violet;
      
      -moz-transform: rotate(180deg);  
      -webkit-transform: rotate(180deg);  
      -o-transform: rotate(180deg);  
      -ms-transform: rotate(180deg); 
      transform: rotate(180deg);
    }
}

div {
  border: 1px black solid;
  width: 100px;
  height: 100px;
  margin: 50px;
}
<div id="animated"></div>

И вот JsFiddle.

Теги:
animation

2 ответа

2
Лучший ответ

Вам нужно сыграть с animation-iteration-count, чтобы исправить это:

const target = document.getElementById("animated");
target.addEventListener("mouseover", animateForward);
target.addEventListener("mouseout", animateBackward);

function animateForward() {
	target.style.animation = '';
  setTimeout(function() {
    target.style.animation = 'custom 1.6s forwards';
    target.style.animationIterationCount = '1';
  }, 0)
}

function animateBackward() {
  target.style.animation = 'custom 1.6s reverse backwards';
  target.style.animationIterationCount = '2';
}
/* Safari 4.0 - 8.0 */
@-webkit-keyframes custom {
    25% {
      border-radius: 50% 0 0 0;
    }
    
    50% {
      border-radius: 50% 50% 0 0;
    }
    
    75% {
      border-radius: 50% 50% 50% 0;
    }
    
    100% {
      border-radius: 50% 50% 50% 50%;
      background-color: violet;
    }
} 

/* Standard syntax */ 
@keyframes custom {
    25% {
      border-radius: 50% 0 0 0;
    }
    
    50% {
      border-radius: 50% 50% 0 0;
    }
    
    75% {
      border-radius: 50% 50% 50% 0;
    }
    
    100% {
      border-radius: 50% 50% 50% 50%;
      background-color: violet;
      
      -moz-transform: rotate(180deg);  
      -webkit-transform: rotate(180deg);  
      -o-transform: rotate(180deg);  
      -ms-transform: rotate(180deg); 
      transform: rotate(180deg);
    }
}

div {
  border: 1px black solid;
  width: 100px;
  height: 100px;
  margin: 50px;
}
<div id="animated"></div>
  • 0
    Да, это работает, спасибо! Но как насчет этой строки: «А если есть способ применить следующую анимацию из той точки, где предыдущая была остановлена, пожалуйста, включите ее в свой ответ» ? Вы знаете, как это реализовать? Было бы очень полезно знать ...
  • 0
    Не могу придумать хорошего решения частичного обратного, но я думаю об этом :)
Показать ещё 4 комментария
2

Для решения только CSS, оставьте @keyframes и вместо этого используйте transitions. Когда вы имеете дело с :hover, переходы - это почти всегда то, что вам действительно нужно.

Например, все свойства вашей анимации могут быть установлены независимо, и, следовательно, они могут иметь свои собственные правила перехода.

Таким образом, ваша анимация может быть преобразована с помощью следующего перехода, где каждый ключевой кадр заменен трио- transition-property - transtion-duration - transition-delay.

div {
  border: 1px black solid;
  width: 100px;
  height: 100px;
  margin: 50px;
  /* define all the props */
  transition-property: 
    transform,
    background-color,
    border-top-left-radius,
    border-top-right-radius,
    border-bottom-right-radius,
    border-bottom-left-radius;
 /* set their duration independently */
 transition-duration: 1.6s, 1.6s, 0.4s, 0.4s, 0.4s, 0.4s;
 /* same for delays */
 transition-delay: 0s, 0s, 0s, 0.4s, 0.8s, 1.2s;
}
div:hover{
  border-radius: 50%;
  background-color: violet;
  transform: rotate(180deg);
  }
<div id="animated"></div>
  • 0
    Спасибо большое, работает отлично! Значит ли это, что у нас больше контроля над анимацией вперед-назад, когда мы используем transitions вместо @keyframes ? И когда мы должны использовать @keyframes ? Только когда нам нужны более сложные анимации с действительно разными @keyframes ? (в моем случае анимация может быть заменена transition вместо @keyframes , потому что все ключевые кадры являются однородными). PS: извините за мой английский
  • 0
    @CommercialSuicide В отличие от переходов, анимации не предназначены для событий, например :hover . Таким образом, мы должны взять их под контроль, а это означает либо жесткий js-код, либо множество объявлений ключевых кадров. Хотя все переходы обрабатываются браузером, браузер сам будет определять, где он находится в анимации, и как вернуться в следующее / предыдущее состояние. Это все зависит от того, что вы делаете. Для повторяющейся анимации, запускаемой только один раз за некоторое время (например, при загрузке графики), анимации лучше подходят.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню