Использование CSS-анимации
==========================

**Экспериментальная возможность:** **Это экспериментальная технология**  
Так как спецификация этой технологии ещё не стабилизировалась, смотрите таблицу совместимости по поводу использования в различных браузерах. Также заметьте, что синтаксис и поведение экспериментальной технологии может измениться в будущих версиях браузеров, вслед за изменениями спецификации.

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

Есть три преимущества CSS-анимации перед традиционными способами:

1. Простота использования для простых анимаций; вы можете создать анимацию, не зная JavaScript.
2. Анимации будут хорошо работать даже при умеренных нагрузках системы. Простые анимации на JavaScript, если они плохо написаны, часто выполняются плохо. Движок может использовать frame-skipping и другие техники, чтобы сохранить производительность на таком высоком уровне .
3. Позволяет браузеру контролировать последовательность анимации, тем самым оптимизируя производительность и эффективность браузера. Например, уменьшая частоту обновления кадров анимации в непросматриваемых в данный момент вкладках.
Конфигурирование анимации
-------------------------

Чтобы создать CSS-анимацию вы должны добавить в стиль элемента, который хотите анимировать, свойство `animation` или его подсвойства. Это позволит вам настроить ускорение и продолжительность анимации, а также другие детали того, как анимация должна протекать. Это не поможет вам настроить внешний вид анимации, который настраивается с помощью `@keyframes` (en-US), рассматриваемой далее в Определение последовательности анимации с помощью ключевых кадров.

Свойство `animation` имеет следующие подсвойства:

`animation-name`

Определяет имя `@keyframes` (en-US), настраивающего кадры анимации.

`animation-duration`

Определяет время, в течение которого должен пройти один цикл анимации.

`animation-timing-function`

Настраивает ускорение анимации.

`animation-delay`

Настраивает задержку между временем загрузки элемента и временем начала анимации.

`animation-iteration-count`

Определяет количество повторений анимации; вы можете использовать значение `infinite` для бесконечного повторения анимации.

`animation-direction`

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

`animation-fill-mode`

Настраивает значения, используемые анимацией, до и после исполнения.

`animation-play-state`

Позволяет приостановить и возобновить анимацию.

Определение последовательности анимации с помощью ключевых кадров
-----------------------------------------------------------------

После того, как вы настроили временные свойства (продолжительность, ускорение) анимации, вы должны определить внешний вид анимации. Это делается с помощью двух и более ключевых кадров после `@keyframes` (en-US). Каждый кадр описывает, как должен выглядеть анимированный элемент в текущий момент.

В то время, как временные характеристики (продолжительность анимации) указываются в стилях для анимируемого элемента, ключевые кадры используют `<percentage>`, чтобы определить стадию протекания анимации. 0% означает начало анимации, а 100% её конец. Так как эти значения очень важны, то для них придумали специальные слова: `from` и `to`.

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

Примеры
-------

**Примечание:** Примеры ниже не используют префиксов для CSS стилей . Webkit-браузеры и старые версии других браузеров нуждаются в указании префиксов в CSS стилях. Примеры, на которые вы можете кликнуть в своём браузере, также содержат префиксы -webkit-.

### Скольжение текста

Этот простой пример анимирует скольжение текста в элементе `<p>` от правого края окна браузера.

Обратите внимание на то, что анимация может сделать страницу шире, чем окно браузера. Этого можно избежать, поместив элемент, который будет анимироваться, в контейнер и установив ему свойство `overflow``: hidden`.


```css
p {
  animation-duration: 3s;
  animation-name: slidein;
}

@keyframes slidein {
  from {
    margin-left: 100%;
    width: 300%;
  }

  to {
    margin-left: 0%;
    width: 100%;
  }
}
```


В стиле для элемента `<p>` с помощью свойства `animation-duration` указано, что исполнение анимации от начала до конца должно занять 3 с , и что имя для `@keyframes` (en-US), описывающей саму анимацию, определено как "slidein".

В элемент `<p>` можно добавлять и другие пользовательские стили, чтобы как-то украсить его, однако здесь мы хотели продемонстрировать только эффект анимации.

Ключевые кадры определяются с помощью правила `@keyframes` (en-US). В данном случае мы имеем только два ключевых кадра. Первый при 0% анимации (`from`). Здесь мы придаём элементу левый отступ в 100% и ширину в 300% (в три раза больше ширины родительского элемента). Это становится причиной того, что при первом кадре анимации заголовок `<p>` находится за пределами правого края окна браузера .

Второй ключевой кадр (to) определяет конец анимации, т.е (100%). Левый отступ устанавливается равным 0, а ширина 100%. Все выглядит так, будто заголовок `<p>` приплывает к левому краю окна браузера.


```html
<p>
  The Caterpillar and Alice looked at each other for some time in silence: at
  last the Caterpillar took the hookah out of its mouth, and addressed her in a
  languid, sleepy voice.
</p>
```


(Обновите страницу, чтобы увидеть анимацию, или щёлкните по кнопке CodePen, чтобы воспроизвести её в окне CodePen)

### Добавление других ключевых кадров

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


```css
75% {
  font-size: 300%;
  margin-left: 25%;
  width: 150%;
}
```



```css
p {
  animation-duration: 3s;
  animation-name: slidein;
}

@keyframes slidein {
  from {
    margin-left: 100%;
    width: 300%;
  }

  to {
    margin-left: 0%;
    width: 100%;
  }

  75% {
    font-size: 300%;
    margin-left: 25%;
    width: 150%;
  }
}
```



```html
<p>
  The Caterpillar and Alice looked at each other for some time in silence: at
  last the Caterpillar took the hookah out of its mouth, and addressed her in a
  languid, sleepy voice.
</p>
```


Это говорит браузеру о том, что при 75% выполнения анимации, шрифт должен быть 300%, а ширина 150%.

(Обновите страницу, чтобы увидеть анимацию, или щёлкните по кнопке CodePen, чтобы воспроизвести её в окне CodePen)

### Настройка повторения

Чтобы настроить повторение, нужно добавить свойство `animation-iteration-count` и задать ему значение, равное нужному количеству повторений анимаций . В данном случае давайте установим значение `infinite` для бесконечного повторения:


```css
p {
  animation-duration: 3s;
  animation-name: slidein;
  animation-iteration-count: infinite;
}
```



```css
@keyframes slidein {
  from {
    margin-left: 100%;
    width: 300%;
  }

  to {
    margin-left: 0%;
    width: 100%;
  }
}
```



```html
<p>
  The Caterpillar and Alice looked at each other for some time in silence: at
  last the Caterpillar took the hookah out of its mouth, and addressed her in a
  languid, sleepy voice.
</p>
```

### Движение текста вправо и влево

Итак, мы настроили повторение, но получили нечто странное: текст при каждом повторении снова "запрыгивает" за край окна браузера. То, чего мы хотим, так это чтобы текст двигался влево и вправо. Этого легко достичь с помощью установки свойству `animation-direction` значения `alternate`:


```css
p {
  animation-duration: 3s;
  animation-name: slidein;
  animation-iteration-count: infinite;
  animation-direction: alternate;
}
```



```css
@keyframes slidein {
  from {
    margin-left: 100%;
    width: 300%;
  }

  to {
    margin-left: 0%;
    width: 100%;
  }
}
```



```html
<p>
  The Caterpillar and Alice looked at each other for some time in silence: at
  last the Caterpillar took the hookah out of its mouth, and addressed her in a
  languid, sleepy voice.
</p>
```

### Использование шорткодов

Шорткод `animation` полезен для экономии места в коде. Например, правило, которое мы используем в этой статье:


```css
p {
  animation-duration: 3s;
  animation-name: slidein;
  animation-iteration-count: infinite;
  animation-direction: alternate;
}
```


можно заменить на:


```css
p {
  animation: 3s infinite alternate slidein;
}
```


**Примечание:** подробнее об этом на странице раздела `animation`

### Установка нескольких значений свойствам анимации

CSS-свойство анимации может иметь несколько значений, разделённых запятыми. Это используется, чтобы указать несколько значений анимации в одном правиле и установить разную продолжительность, число повторений и т.д., для различных анимаций. Рассмотрим несколько примеров, чтобы увидеть разницу.

В первом примере у свойства имени анимации установлены три значения, у свойств продолжительности и количества повторений — по одному. В этом случае у всех трёх анимаций одинаковая продолжительность и число повторений:


```css
animation-name: fadeInOut, moveLeft300px, bounce;
animation-duration: 3s;
animation-iteration-count: 1;
```


Во втором примере установлены три значения для каждого из свойств. В этом случае каждая анимация выполняется с соответствующими по порядку значениями в каждом свойстве, так, например, `fadeInOut` имеет продолжительность 2.5 с и количество повторений 2, и т.д.


```css
animation-name: fadeInOut, moveLeft300px, bounce;
animation-duration: 2.5s, 5s, 1s;
animation-iteration-count: 2, 1, 5;
```


В третьем примере определены три значения имени анимации, но два значения продолжительности и количества повторений. В случае, когда количества значений недостаточно для каждой анимации, значения берутся циклически от начала до конца. Например, у `fadeInOut` длительность будет 2.5s, а `moveLeft300px` — 5s. Значения продолжительности закончились, теперь они берутся сначала — `bounce` получит продолжительность 2.5s. Значение количества повторений (а также другие указанные свойства) будет определено таким же образом.


```css
animation-name: fadeInOut, moveLeft300px, bounce;
animation-duration: 2.5s, 5s;
animation-iteration-count: 2, 1;
```

### Использование событий анимации

Вы можете получить дополнительный контроль над анимацией, а также полезную информацию о ней, с помощью *событий анимации*. Эти события, представленные объектом `AnimationEvent` (en-US), можно использовать, чтобы определить, когда начинается и заканчивается анимация или начинается новая итерация. Каждое событие содержит момент времени, когда оно произошло, а также имя анимации, которая вызвала событие.

Мы будем модифицировать текст, чтобы выводить некоторую информацию о каждом событии анимации. Так мы сможем увидеть, как она работает.

#### Добавление CSS

Начнём с добавления CSS. Анимация будет длиться 3 секунды, будет называться "slidein", будет повторяться 3 раза, а также значение animation-direction установлено alternate. В ключевых кадрах `@keyframes` (en-US) установлены такие значения ширины и левого отступа, что элемент будет скользить по экрану.


```css
.slidein {
  -moz-animation-duration: 3s;
  -webkit-animation-duration: 3s;
  animation-duration: 3s;
  -moz-animation-name: slidein;
  -webkit-animation-name: slidein;
  animation-name: slidein;
  -moz-animation-iteration-count: 3;
  -webkit-animation-iteration-count: 3;
  animation-iteration-count: 3;
  -moz-animation-direction: alternate;
  -webkit-animation-direction: alternate;
  animation-direction: alternate;
}

@-moz-keyframes slidein {
  from {
    margin-left: 100%;
    width: 300%;
  }

  to {
    margin-left: 0%;
    width: 100%;
  }
}

@-webkit-keyframes slidein {
  from {
    margin-left: 100%;
    width: 300%;
  }

  to {
    margin-left: 0%;
    width: 100%;
  }
}

@keyframes slidein {
  from {
    margin-left: 100%;
    width: 300%;
  }

  to {
    margin-left: 0%;
    width: 100%;
  }
}
```


#### Добавление обработчика события анимации

Будем использовать JavaScript для отслеживания всех трёх возможных событий анимации. Следующий код конфигурирует обработчик; мы вызываем его при первой загрузке документа.


```js
var e = document.getElementById("watchme");
e.addEventListener("animationstart", listener, false);
e.addEventListener("animationend", listener, false);
e.addEventListener("animationiteration", listener, false);

e.className = "slidein";
```


Это довольно стандартный код; вы можете получить дополнительную информацию в документации `element.addEventListener()`. Последнее, что делает этот код - это установка класса "slidein" для анимируемого элемента; мы делаем это, чтобы запустить анимацию.

Почему? Потому что в нашем случае событие `animationstart` происходит как только анимация стартует, и это происходит раньше, чем исполняется наш сценарий. Так мы сможем контролировать начало анимации самостоятельно посредством вставки класса "slidein" для анимируемого элемента.

#### Регистрация событий

События будут передаваться функции `listener()`, показанной ниже.


```js
function listener(e) {
  var l = document.createElement("li");
  switch (e.type) {
    case "animationstart":
      l.innerHTML = "Started: elapsed time is " + e.elapsedTime;
      break;
    case "animationend":
      l.innerHTML = "Ended: elapsed time is " + e.elapsedTime;
      break;
    case "animationiteration":
      l.innerHTML = "New loop started at time " + e.elapsedTime;
      break;
  }
  document.getElementById("output").appendChild(l);
}
```


Этот код также очень прост. Этот код следит за `event.type`, чтобы определить тип события, и добавляет элемент `<ul>`, чтобы залогировать произошедшее событие.

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

* Started: elapsed time is 0
* New loop started at time 3.01200008392334
* New loop started at time 6.00600004196167
* Ended: elapsed time is 9.234000205993652

Обратите внимание, что время, указанное в выводе, и время, которое мы указали в стилях, не совпадают. Также обратите внимание, что после окончания итерации не посылается событие `animationiteration` ; вместо него посылается событие `animationend`.

#### HTML

Ради полноты картины приведём код разметки HTML. В разметке имеется тег *ul,* в который и выводится вся информация:


```html
<body>
  <h1 id="watchme">Watch me move</h1>
  <p>
    This example shows how to use CSS animations to make <code>p</code> elements
    move across the page.
  </p>
  <p>
    In addition, we output some text each time an animation event fires, so you
    can see them in action.
  </p>
  <ul id="output"></ul>
</body>
```

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

* `AnimationEvent`
* Использование CSS-переходов (en-US)