Как я могу позволить моей анимации гамбургера вернуться?

Я не могу заставить мою анимацию работать плавно.

Я создал иконку бургера, с тремя элементами, например:

<div class="container">
<div class="burger-contain">
    <div id="line-1" class="line"></div>
    <div id="line-2" class="line"></div>
    <div id="line-3" class="line"></div>
</div>
</div>

У меня есть три разных ключевых кадра для каждой строки.

.line:first-child {
   animation-name: firstChild;
   transform-origin: 30px 25px;
   animation-duration: 0.5s;
   animation-fill-mode: forwards;
   margin: 10px;
}

Тогда ключевые кадры:

@keyframes firstChild {
0% {transform: translateY(0);}
50% {transform: translateY(10px);}
100% {transform: rotate(-45deg);}
}

Все три имеют немного различную анимацию. Ребенок два только исчезает, а ребенок три идет вверх, а не вниз.

Чтобы сделать функцию щелчка, я использую jquery для добавления / удаления классов следующим образом:

$(document).ready(function(){

var line = $(".line");
var burger = $(".burger-contain")
var toggled = false;

burger.click(function(){
   triggerAnimation();
});

function triggerAnimation(){
   if (toggled === false){
   line.removeClass("reverse");
   line.addClass("animate");
   toggled = true;
} else {

   line.removeClass("animate");
   line.addClass("reverse");
   toggled = false; 
}

}


});

Тогда мой план обратить анимацию в том, чтобы использовать CSS animation-direction: reverse; как это:

.line:first-child.reverse {
animation-name: firstChild;
transform-origin: 30px 25px;
animation-duration: 0.5s;
animation-fill-mode: forwards;
margin: 10px;
animation-direction: reverse;
}

Снова по всем трем линиям.

Однако проблема в том, что пока первая анимация идет нормально. Во второй раз это перестает анимировать все вместе. Между состояниями Бургера и Креста нет перехода. Как вперед-назад, так и анимацию можно использовать только один раз.

Моя логика неверна или я неправильно понимаю использование обратной анимации?

2 ответа

Решение

Ваше понимание обратного не совсем верно.

Анимация воспроизводится в обратном направлении каждого цикла. Другими словами, каждый раз, когда анимация циклически повторяется, анимация сбрасывается в конечное состояние и начинается снова. Этапы анимации выполняются в обратном направлении, а функции синхронизации также меняются местами. Например, функция синхронизации замедления становится замедлением. ссылка

В вашем случае анимация уже закончилась, поэтому добавление reverse не будет запускать анимацию снова, она просто переключит начальное и конечное состояние.

Вот упрощенный пример. При наведении курсора вы увидите, что анимация будет прыгать, а не менять направление плавно, потому что мы переворачиваем всю анимацию и не перемещаем элемент туда, где он находится. Это как смотреть в зеркало:

.box {
  width:50px;
  height:50px;
  background:red;
  animation:change 5s linear forwards;
}

@keyframes change {
  from {transform:translateX(0)}
  to {transform:translateX(300px)}
}

body:hover .box{
   animation-direction:reverse;
}
<div class="box">

</div>

Когда анимация завершена, вы можете четко заметить, как при наведении мыши мы переключаем первое и последнее состояние.


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

Я использовал hover, но вы можете легко заменить класс, который вы добавляете / удаляете

.menu {
  height:50px;
  width:60px;
  position:relative;
  margin:50px;
  background:
    linear-gradient(#000,#000) center/100% 10px no-repeat;
  transition:all 0s 0.5s;
}
.menu:before,
.menu:after{
  content:"";
  position:absolute;
  left:0;
  height:10px;
  width:100%;
  background:#000;
  transition:0.5s 0.5s top,0.5s 0.5s bottom,0.5s transform;
}
.menu:before {
  top:0;
}
.menu:after {
  bottom:0;
}

.menu:hover {
  background-size:0px 0px;
}

.menu:hover:before {
  top:calc(50% - 5px);
  transform:rotate(45deg);
  transition:0.5s top,0.5s 0.5s transform;
}

.menu:hover:after {
  bottom:calc(50% - 5px);
  transform:rotate(-45deg);
  transition:0.5s bottom,0.5s 0.5s transform;
}
<div class="menu">
  
</div>

Рабочая скрипка: https://jsfiddle.net/upnhcw69/38/

Чтобы решить эту проблему, нам нужно иметь 2 анимации и менять их одну на другую, тогда они корректно срабатывают.

После первого клика анимация firstChild запускается после второго клика анимация firstChild2. Мы используем 2 класса с разными анимациями.

.line{
   height: 10px;
   width: 100px;
   margin: 10px;
   background-color:red;
}

@keyframes firstChild {
  0% {transform: translateY(0);}
  50% {transform: translateY(10px);}
  100% {transform: rotate(-45deg);}
}

@keyframes firstChild2 {
  0% {transform: rotate(-45deg);}
  50% {transform: translateY(10px);}
  100% {transform: rotate(0deg);}
}

.animate {
   animation-name: firstChild;
   transform-origin: 30px 25px;
   animation-duration: 0.5s;
   animation-fill-mode: forwards;
}

.reverse {
    animation-name: firstChild2;
   transform-origin: 30px 25px;
   animation-duration: 0.5s;
}
Другие вопросы по тегам