Spec-Zone.ru › CSS

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

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

Существует три ключевых преимущества анимаций CSS по сравнению с традиционными методами анимации на основе сценариев:

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

Настройка анимации

Для создания последовательности анимации CSS необходимо стилизовать элемент, который вы хотите анимировать, с помощью свойства animation или его подсвойств. Это позволяет настроить время, длительность и другие детали того, как должна проходить последовательность анимации. Это не настраивает фактическое отображение анимации, что выполняется с помощью правила @keyframes, как описано в разделе «Определение последовательности анимации с помощью ключевых кадров» ниже.

Подсвойства свойства animation:

animation-composition

Устанавливает композицию операций, используемую, когда несколько анимаций одновременно влияют на одно свойство. Это свойство не является частью сокращенного свойства animation.

animation-delay

Устанавливает задержку между загрузкой элемента и началом последовательности анимации, а также то, должно ли начать анимация сразу с начала или на определенной стадии анимации.

animation-direction

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

animation-duration

Устанавливает длительность времени, в течение которого анимация проходит один цикл.

animation-fill-mode

Определяет, как анимация применяет стили к своему объекту до и после ее запуска.

Примечание: В случае режима заполнения анимации forwards анимированные свойства ведут себя так, как если бы они были включены в значение свойства will-change. Если в процессе анимации был создан новый контекст стека, целевой элемент сохраняет контекст стека после завершения анимации.

animation-iteration-count

Устанавливает количество повторений анимации.

animation-name

Указывает имя правила @keyframes, описывающего ключевые кадры анимации.

animation-play-state

Указывает, нужно ли приостановить или возобновить последовательность анимации.

animation-timeline

Устанавливает временную шкалу, которая используется для управления ходом CSS-анимации.

animation-timing-function

Определяет, как анимация переходит от одного ключевого кадра к другому, задавая кривые ускорения.

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

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

Поскольку время анимации определяется в стиле CSS, который настраивает анимацию, ключевые кадры используют <percentage> для указания времени в последовательности анимации, в котором они происходят. 0% указывает первый момент последовательности анимации, а 100% — конечное состояние анимации. Поскольку эти два момента очень важны, они имеют специальные псевдонимы: from и to. Оба являются необязательными. Если from/0% или to/100% не указаны, браузер запускает или завершает анимацию, используя вычисленные значения всех атрибутов.

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

Использование сокращенного свойства animation

Сокращенное свойство animation полезно для экономии места. В качестве примера, некоторые правила, которые мы использовали в этой статье:

p {
  animation-duration: 3s;
  animation-name: slide-in;
  animation-iteration-count: infinite;
  animation-direction: alternate;
}

...могут быть заменены с помощью сокращенного свойства animation.

p {
  animation: 3s infinite alternate slide-in;
}

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

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

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

В этом первом примере есть три значения длительности и три значения количества повторений. Таким образом, каждой анимации присваивается значение длительности и количества повторений в том же положении, что и имя анимации. Анимации fadeInOut присвоена длительность 2.5s и количество повторений 2, а анимации bounce присвоена длительность 1s и количество повторений 5.

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

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

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

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

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

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

Примеры

Примечание: Некоторые старые браузеры (до 2017 года) могут потребовать префиксов; примеры, которые вы можете нажать, чтобы посмотреть в браузере, включают префиксную синтаксис -webkit.

Перемещение текста по окну браузера

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

p {
  animation-duration: 3s;
  animation-name: slide-in;
}

@keyframes slide-in {
  from {
    translate: 150vw 0;
    scale: 200% 1;
  }

  to {
    translate: 0 0;
    scale: 100% 1;
  }
}

В этом примере стиль элемента <p> указывает, что анимация должна выполняться в течение 3 секунд, используя свойство animation-duration, и что имя правила @keyframes, определяющего ключевые кадры последовательности анимации, равно slide-in.

В данном случае у нас всего два ключевых кадра. Первый происходит в момент 0% (используя псевдоним from). Здесь мы настраиваем свойство translate элемента на значение 150vw (то есть, за пределами правого края содержащего элемента), а свойство scale элемента на 200% (или в два раза больше его значения по умолчанию), что делает абзац в два раза шире его <body> содержащего блока. Это приводит к тому, что в первом кадре анимации заголовок отображается за правым краем окна браузера.

Второй ключевой кадр происходит в момент 100% (используя псевдоним to). Свойство translate устанавливается в значение 0%, а свойство scale элемента устанавливается в значение 1, что равно 100%. Это заставляет заголовок завершить анимацию в своем состоянии по умолчанию, примыкая к левому краю области содержимого.

<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>

Примечание: Перезагрузите страницу, чтобы увидеть анимацию.

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

Давайте добавим ещё один ключевой кадр к анимации предыдущего примера. Предположим, что мы хотим, чтобы имя Алисы стало розовым, увеличилось в размерах, а затем уменьшилось до исходного размера и цвета по мере перемещения справа налево. Хотя мы могли бы изменить font-size, изменение любых свойств, влияющих на модель блока, негативно сказывается на производительности. Вместо этого мы обернём её имя в <span> и затем изменим масштаб и зададим цвет отдельно. Это требует добавления второй анимации, влияющей только на <span>:

@keyframes grow-shrink {
  25%,
  75% {
    scale: 100%;
  }

  50% {
    scale: 200%;
    color: magenta;
  }
}

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

p {
  animation-duration: 3s;
  animation-name: slide-in;
}
p span {
  display: inline-block;
  animation-duration: 3s;
  animation-name: grow-shrink;
}

@keyframes slide-in {
  from {
    translate: 150vw 0;
    scale: 200% 1;
  }

  to {
    translate: 0 0;
    scale: 100% 1;
  }
}

@keyframes grow-shrink {
  25%,
  75% {
    scale: 100%;
  }

  50% {
    scale: 200%;
    color: magenta;
  }
}

Мы добавили <span> вокруг "Алисы":

<p>
  The Caterpillar and <span>Alice</span> 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>

Это говорит браузеру, что имя должно быть нормальным в первые и последние 25% анимации, но стать розовым и увеличиться в размерах, а затем уменьшиться снова в середине. Мы установили свойство display для тегов в значение inline-block, так как свойства transform не влияют на не-замещаемый inline-контент.

Примечание: Перезагрузите страницу, чтобы увидеть анимацию.

Повторение анимации

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

p {
  animation-duration: 3s;
  animation-name: slide-in;
  animation-iteration-count: infinite;
}

Движение анимации вперёд и назад

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

p {
  animation-duration: 3s;
  animation-name: slide-in;
  animation-iteration-count: infinite;
  animation-direction: alternate;
}

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

Вы можете получить дополнительный контроль над анимациями — а также полезную информацию о них — с помощью событий анимации. Эти события, представленные объектом AnimationEvent, могут использоваться для обнаружения начала, окончания и начала новой итерации анимаций. Каждое событие включает время его возникновения, а также имя анимации, которая его спровоцировала.

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

Мы включили ту же анимацию ключевых кадров, что и в предыдущем примере. Эта анимация будет длиться 3 секунды, называться "slide-in", повторяться 3 раза и каждый раз перемещаться в другом направлении. В правилах @keyframes манипулируются масштабом и перемещением по оси x, чтобы элемент скользил по экрану.

.slide-in {
  animation-duration: 3s;
  animation-name: slide-in;
  animation-iteration-count: 3;
  animation-direction: alternate;
}

Добавление слушателей событий анимации

Мы будем использовать JavaScript-код для прослушивания всех трёх возможных событий анимации. Этот код настраивает наши слушатели событий; мы вызываем его при первой загрузке документа, чтобы всё настроить.

const element = document.getElementById("watch-me");
element.addEventListener("animationstart", listener, false);
element.addEventListener("animationend", listener, false);
element.addEventListener("animationiteration", listener, false);

element.className = "slide-in";

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

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

Получение событий

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

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

Этот код тоже очень прост. Он проверяет event.type, чтобы определить тип события анимации, а затем добавляет соответствующую запись в <ul> (неупорядоченный список), который мы используем для регистрации этих событий.

Выходной результат, в конечном итоге, выглядит примерно так:

  • Начато: время задержки составляет 0
  • Новый цикл начался в момент времени 3.01200008392334
  • Новый цикл начался в момент времени 6.00600004196167
  • Закончено: время задержки составляет 9.234000205993652

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

Для полноты картины, вот HTML, отображающий содержимое страницы, включая список, в который скрипт вставляет информацию о полученных событиях:

<h1 id="watch-me">Watch me move</h1>
<p>
  This example shows how to use CSS animations to make <code>H1</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>

И вот живой вывод.

Примечание: Перезагрузите страницу, чтобы увидеть анимацию.

END_OF_DOCUMENT_MARKER ```

Анимация отображения и видимости содержимого

В этом примере показано, как можно анимировать display и content-visibility. Это полезно для создания анимаций входа/выхода, где, например, вы хотите удалить контейнер из DOM с помощью display: none, но плавно скрыть его с помощью opacity, а не мгновенно.

Поддерживающие браузеры анимируют display и content-visibility с использованием варианта типа анимации дискретной анимации. Это, как правило, означает, что свойства будут переключаться между двумя значениями на 50% пути анимации между ними.

Однако есть исключение, когда анимация выполняется к/от display: none или content-visibility: hidden до видимого значения. В этом случае браузер будет переключаться между значениями таким образом, что анимируемое содержимое будет отображаться в течение всего времени анимации.

Например:

  • При анимации display от none до block (или другого видимого display значения), значение переключится на block на 0% длительности анимации, чтобы оно было видно на протяжении всего времени анимации.
  • При анимации display от block (или другого видимого display значения) до none, значение переключится на none на 100% длительности анимации, чтобы оно было видно на протяжении всего времени анимации.

HTML

HTML содержит два <p> элемента с <div> между ними, которые мы будем анимировать от display none до block.

<p>
  Click anywhere on the screen or press any key to toggle the
  <code>&lt;div&gt;</code> between hidden and showing.
</p>

<div>
  This is a <code>&lt;div&gt;</code> element that animates between
  <code>display: none; opacity: 0</code> and
  <code>display: block; opacity: 1</code>. Neat, huh?
</div>

<p>
  This is another paragraph to show that <code>display: none;</code> is being
  applied and removed on the above <code>&lt;div&gt; </code>. If only its
  <code>opacity</code> was being changed, it would always take up the space in
  the DOM.
</p>

CSS

html {
  height: 100vh;
}

div {
  font-size: 1.6rem;
  padding: 20px;
  border: 3px solid red;
  border-radius: 20px;
  width: 480px;
  opacity: 0;
  display: none;
}

/* Animation classes */

div.fade-in {
  display: block;
  animation: fade-in 0.7s ease-in forwards;
}

div.fade-out {
  animation: fade-out 0.7s ease-out forwards;
}

/* Animation keyframes */

@keyframes fade-in {
  0% {
    opacity: 0;
    display: none;
  }

  100% {
    opacity: 1;
    display: block;
  }
}

@keyframes fade-out {
  0% {
    opacity: 1;
    display: block;
  }

  100% {
    opacity: 0;
    display: none;
  }
}

Обратите внимание на включение свойства display в анимации ключевых кадров.

JavaScript

Наконец, мы включаем немного JavaScript для настройки обработчиков событий для запуска анимаций. В частности, мы добавляем класс fade-in к <div>, когда хотим его отобразить, и fade-out когда хотим его скрыть.

const divElem = document.querySelector("div");
const htmlElem = document.querySelector(":root");

htmlElem.addEventListener("click", showHide);
document.addEventListener("keydown", showHide);

function showHide() {
  if (divElem.classList[0] === "fade-in") {
    divElem.classList.remove("fade-in");
    divElem.classList.add("fade-out");
  } else {
    divElem.classList.remove("fade-out");
    divElem.classList.add("fade-in");
  }
}

Результат

Код отображается следующим образом:

См. также

  • AnimationEvent
  • Использование CSS-переходов
  • Использование API веб-анимаций

© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animations/Using_CSS_animations

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API