Переключение анимации CSS3 по клику

Каков наилучший способ изменить направление анимации CSS3 при нажатии без javascript?

В последнее время я изучал хаки с флажками и пытался найти способ иметь только один набор ключевых кадров вместо двух наборов для одного перехода вперед и одного назад. Это возможно? Или есть способ сделать это с одним набором?

Например, у меня есть следующие ключевые кадры:

@keyframes moveIt {
  0%   { 
    transform: translateX(0);
    width: $size;
  }
  50%  {
    width: $size*1.2;
  }
  100% {
    transform: translateX(50px);
    width: $size;
  }
}
@keyframes moveItBack {
  100%   { 
    transform: translateX(0);
    width: $size;
  }
  50%  {
    width: $size*1.2;
  }
  0% {
    transform: translateX(50px);
    width: $size;
  }
}

Есть ли способ уменьшить это только до первого набора? Затем при возвращении начать со 100% и вернуться к 0%?

Вот пример того, что я пытаюсь сделать.


person souporserious    schedule 30.04.2014    source источник
comment
Я использовал вариант хака с флажком, с двумя переключателями (каждая со своей меткой) и двумя зеркальными анимациями. Громоздко, но вполне эффективно. jsfiddle.net/mblase75/5cnsn38L/5   -  person Blazemonger    schedule 22.10.2015


Ответы (2)


CSS на самом деле не предназначен для чего-то подобного, но есть некоторые обходные пути.

Оптимально мы могли бы сделать что-то вроде следующего, потому что это имеет логический смысл

.bubble {
  ...
  animation: moveIt .25s forwards ease-out;
}
input[type=checkbox]:checked ~ .bubble {
  animation: moveIt .25s backwards ease-out;
}

Однако с помощью чистого CSS[1] нельзя выполнить сброс или изменить анимацию на другую. Это связано с тем, что каждому элементу разрешено иметь только одну анимацию. Вы можете сбросить его в javascript, используя setTimeout или клонировав элемент, но я предполагаю, что вы пытаетесь этого избежать.

Таким образом, у вас остается два варианта. Первый — отказаться от изменения размера и просто переключить translateX вот так:

.bubble {
  ...
  transition: all .25s ease-out;
}
input[type=checkbox]:checked ~ .bubble {
  transform: translateX(50px);
}

Другой вариант сохранить изменение размера — сделать что-то более сложное. Вы можете фактически имитировать изменение размера, используя псевдоэлементы. Переключая анимацию обоих противоположных друг другу, вы можете сделать так, чтобы весь элемент выглядел так, будто он пульсирует каждый раз. Демо

.bubble {
  ...
  transition: all .25s ease-out;
}
.bubble:after, .bubble:before {
  content:''; 
  position:absolute;
  width:100%; height:100%;
  background:inherit;
  border-radius:inherit;
  animation:'';
}
.bubble:before { animation:size .25s ease-out; }
input[type=checkbox]:checked ~ .bubble:before { animation:''; }
input[type=checkbox]:checked ~ .bubble {
  transform: translateX(50px);
}
input[type=checkbox]:checked ~ .bubble:after {
  animation:size .25s ease-out;
}
@keyframes size {
  50% { transform:scale(1.2); }
}

Я надеюсь, что это имеет смысл!

[1]: как показано во втором варианте, это возможно, просто требуется состояние удаления прошлой анимации. К сожалению, что-то вроде animation:''; animation:moveIt .25s backwards ease-out; не сбрасывает его

person Zach Saucier    schedule 30.04.2014
comment
Оцените подробный ответ! Спасибо за разъяснения, а также за исправление моего вопроса. - person souporserious; 30.04.2014

Это должно сделать то же самое, просто удвоить продолжительность.

@keyframes moveIt {
  0%   { 
    transform: translateX(0);
    width: $size;
  }
  25% {
    width: $size*1.2;
  }
  50%  {
    transform: translateX(50px);
  }
  75% {
    width: $size*1.2;
  }
  100% {
    transform: translateX(0);
    width: $size;
  }
}
person JimmyRare    schedule 30.04.2014
comment
Извините, нужно было быть более конкретным. Я хотел бы иметь возможность переключать это состояние и возвращаться из него. Так что не все сразу, а переключите первую анимацию, затем снова включите ее и вернитесь назад. - person souporserious; 30.04.2014