CSS Animations tips and tricks

Этот перевод не завершён. Пожалуйста, помогите перевести эту статью с английского

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

Запустить анимацию снова

Спецификация CSS Animations не предлагает способа запустить анимацию снова. Нет никакого волшебного метода resetAnimation () для элементов, и вы даже не можете просто установить элемент animation-play-state в" running " снова. Вместо этого вы должны использовать хитрые трюки, чтобы запустить остановленную анимацию для воспроизведения.

Предлагаем вам один из способов, который мы считаем достаточно надежным и стабильным.

HTML содержимое

Во-первых, давайте определим HTML для <div> который мы хотим анимировать, и кнопку, которая будет запускать (или воспроизводить) анимацию.

<div class="box">
</div>

<div class="runButton">Click me to run the animation</div>

CSS содержимое

Теперь мы определим саму анимацию с помощью CSS. Некоторые стили CSS, которые не важны (стиль самой кнопки "выполнить"), здесь не показаны, для краткости.

@keyframes colorchange {
  0% { background: yellow }
  100% { background: blue }
}

.box {
  width: 100px;
  height: 100px;
  border: 1px solid black;
}

.changing {
  animation: colorchange 2s;
}

Здесь есть два класса. В классе "box" прописано основное описание внешнего вида элемента, без какой-либо анимационной информации. Детали анимации включены в класс "changing" , который сообщает, что @keyframes с именем "colorchange" должен использоваться в течение 2 секунд.

Обратите внимание, что каких-либо анимационных эффектов у элемента не наблюдается, т.е. анимации нет.

JavaScript содержимое

Далее мы рассмотрим JavaScript, который дополняет эту работу. Основа этой техники находится в функции play (), которая вызывается, когда пользователь нажимает на кнопку "Выполнить".

function play() {
  document.querySelector(".box").className = "box";
  window.requestAnimationFrame(function(time) {
    window.requestAnimationFrame(function(time) {
      document.querySelector(".box").className = "box changing";
    });
  });
}

Это выглядит странно, не так ли? Это потому, что единственный способ воспроизвести анимацию снова-удалить анимационный эффект, позволить документу пересчитать стили так, чтобы он знал, что вы это сделали, а затем добавить анимационный эффект обратно в элемент. Чтобы это произошло, мы должны быть креативными.

Вот что происходит, когда вызывается функция play() :

  1. Список классов CSS в элементе сбрасывается до простого "box". Это приводит к удалению всех других классов, которые в настоящее время применяются к элементу, включая класс "changing" , который обрабатывает анимацию. Другими словами, мы удаляем анимационный эффект из элемента. Однако изменения в списке классов не вступают в силу до тех пор, пока не будет завершен перерасчет стиля и не произойдет обновление, отражающее это изменение.
  2. Чтобы убедиться, что стили пересчитаны, мы используем  window.requestAnimationFrame(), указывающую обратный вызов. Наш обратный вызов выполняется непосредственно перед следующей перерисовкой документа. Проблема заключается в том,что, поскольку это происходит до перерисовки, перерасчет стиля еще не произошел! 
  3. Наш обратный вызов ловко вызывает requestAnimationFrame() второй раз! На этот раз обратный вызов выполняется до следующей перерисовки, то есть после того, как произошла перерасчет стиля. Этот обратный вызов добавляет класс "changing" обратно в элемент, так что перерисовка снова запустит анимацию.

Конечно, нам также нужно добавить обработчик событий к нашей кнопке "выполнить", чтобы она действительно что-то делала:

document.querySelector(".runButton").addEventListener("click", play, false);

Результат

Остановка анимации

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

  1. Сделайте свою анимацию настолько самодостаточной, насколько это возможно. Это означает, что вы не должны полагаться на animation-direction: alternate. Вместо этого вы должны явно написать анимацию ключевого кадра, которая проходит через полную анимацию в одном прямом повторении.
  2. Используйте JavaScript и очистите анимацию, используемую при запуске событияanimationiteration .

Следующая демонстрация показывает, как вы могли бы достичь вышеупомянутой техники JavaScript:

.slidein {
  animation-duration: 5s;
  animation-name: slidein;
  animation-iteration-count: infinite;
}

.stopped {
  animation-name: none;
}

@keyframes slidein {
  0% {
    margin-left: 0%;
  }
  50% {
    margin-left: 50%;
  }
  100% {
    margin-left: 0%;
  }
}
<h1 id="watchme">Click me to stop</h1>
let watchme = document.getElementById('watchme')

watchme.className = 'slidein'
const listener = (e) => {
  watchme.className = 'slidein stopped'
}
watchme.addEventListener('click', () =>
  watchme.addEventListener('animationiteration', listener, false)
)

Demo https://jsfiddle.net/morenoh149/5ty5a4oy/

Смотрите также