Внести вклад
Расширенная экосистема
Устаревшие анимации

Миграция с пакета Angular Animations

Пакет @angular/animations устарел начиная с v20.2, которая также представила новые возможности animate.enter и animate.leave для добавления анимаций в приложение. Используя эти новые возможности, можно заменить все анимации на основе @angular/animations обычным CSS или JS-библиотеками анимаций. Удаление @angular/animations из приложения может значительно уменьшить размер JavaScript-бандла. Нативные CSS-анимации обычно дают лучшую производительность, так как могут использовать аппаратное ускорение. Это руководство проводит через процесс рефакторинга кода с @angular/animations на нативные CSS-анимации.

Как писать анимации на нативном CSS

Если вы никогда не писали нативные CSS-анимации, есть ряд отличных руководств для старта. Вот некоторые из них:
MDN's CSS Animations guide
W3Schools CSS3 Animations guide
The Complete CSS Animations Tutorial
CSS Animation for Beginners

и пара видео:
Learn CSS Animation in 9 Minutes
Net Ninja CSS Animation Tutorial Playlist

Ознакомьтесь с этими руководствами и туториалами, затем вернитесь к этому гайду.

Создание переиспользуемых анимаций

Как и с пакетом animations, можно создавать переиспользуемые анимации, которыми можно делиться по всему приложению. Версия пакета animations требовала использования функции animation() в общем typescript-файле. Нативная CSS-версия похожа, но живёт в общем CSS-файле.

С пакетом Animations

animations.ts

export const sharedAnimation = animation([
  style({
    height: 0,
    opacity: 1,
    backgroundColor: 'red',
  }),
  animate('1s'),
]);

С нативным CSS

animations.css

@keyframes sharedAnimation {
  to {
    height: 0;
    opacity: 1;
    background-color: 'red';
  }
}

.animated-class {
  animation: sharedAnimation 1s;
}

Добавление класса animated-class к элементу запускает анимацию на этом элементе.

Анимация перехода

Анимация состояний и стилей

Пакет animations позволял определять различные состояния с помощью функции state() внутри компонента. Примеры — состояния open или closed, содержащие стили для каждого соответствующего состояния в определении. Например:

С пакетом Animations

open-close.ts

// ...
      state(
        'open',
        style({
          height: '200px',
          opacity: 1,
          backgroundColor: 'yellow',
        }),
      ),

То же поведение можно реализовать нативно с помощью CSS-классов — либо с keyframe-анимацией, либо с transition-стилями.

С нативным CSS

animations.css

.open {
  height: '200px';
  opacity: 1;
  background-color: 'yellow';
  transition: all 1s;
}

.closed {
  height: '100px';
  opacity: 0.8;
  background-color: 'blue';
  transition: all 1s;
}

Запуск состояния open или closed выполняется переключением классов на элементе в компоненте. Примеры того, как это сделать, есть в нашем руководстве по шаблонам.

Похожие примеры есть в руководстве по шаблонам для прямой анимации стилей.

Transitions, timing и easing

Функция animate() пакета animations позволяет задавать timing — duration, delays и easing. Это можно сделать нативно в CSS с помощью нескольких CSS-свойств или shorthand-свойств.

Укажите animation-duration, animation-delay и animation-timing-function для keyframe-анимации в CSS, либо используйте shorthand-свойство animation.

animations.css

.example-element {
  animation-duration: 1s;
  animation-delay: 500ms;
  animation-timing-function: ease-in-out;
}

.example-shorthand {
  animation: exampleAnimation 1s ease-in-out 500ms;
}

Аналогично можно использовать transition-duration, transition-delay и transition-timing-function и shorthand transition для анимаций, не использующих @keyframes.

animations.css

.example-element {
  transition-duration: 1s;
  transition-delay: 500ms;
  transition-timing-function: ease-in-out;
  transition-property: margin-right;
}

.example-shorthand {
  transition: margin-right 1s ease-in-out 500ms;
}

Запуск анимации

Пакет animations требовал указывать triggers с помощью функции trigger() и вкладывать все состояния внутрь. С нативным CSS это не нужно. Анимации можно запускать переключением CSS-стилей или классов. Как только класс присутствует на элементе, анимация произойдёт. Удаление класса вернёт элемент к тому CSS, который определён для этого элемента. В результате значительно меньше кода для той же анимации. Вот пример:

С пакетом Animations

С нативным CSS

Transition и triggers

Предопределённые состояния и wildcard matching

Пакет animations предлагает возможность сопоставлять определённые состояния с transition через строки. Например, анимация из open в closed была бы open => closed. Можно использовать wildcards для сопоставления любого состояния с целевым, например * => closed, а ключевое слово void можно использовать для состояний входа и выхода. Например: * => void когда элемент покидает view, или void => * когда элемент входит в view.

Эти паттерны сопоставления состояний вообще не нужны при анимации напрямую через CSS. Можно управлять тем, какие transitions и @keyframes-анимации применяются, на основе классов и/или стилей, которые вы задаёте на элементах. Также можно добавить @starting-style, чтобы контролировать, как элемент выглядит сразу при входе в DOM.

Автоматический расчёт свойств с wildcards

Пакет animations предлагает возможность анимировать то, что исторически было сложно анимировать — например, анимацию заданной высоты до height: auto. Теперь это можно сделать и на чистом CSS.

С пакетом Animations

Можно использовать CSS Grid для анимации до auto height.

С нативным CSS

Если не нужно поддерживать все браузеры, также можно посмотреть calc-size() — настоящее решение для анимации auto height. См. документацию MDN и этот туториал для дополнительной информации.

Анимация входа и выхода из view

Пакет animations предлагал упомянутое выше сопоставление паттернов для входа и выхода, а также включал shorthand-алиасы :enter и :leave.

С пакетом Animations

С нативным CSS

С нативным CSS

Подробнее о animate.enter и animate.leave см. в руководстве Enter and Leave animations.

Анимация increment и decrement

Наряду с упомянутыми :enter и :leave есть также :increment и :decrement. Их тоже можно анимировать добавлением и удалением классов. В отличие от встроенных алиасов пакета animations, нет автоматического применения классов при увеличении или уменьшении значений. Можно применять соответствующие классы программно. Вот пример:

С пакетом Animations

С нативным CSS

Parent / Child анимации

В отличие от пакета animations, когда в компоненте указано несколько анимаций, ни одна анимация не имеет приоритета над другой и ничто не блокирует запуск любой анимации. Любая последовательность анимаций должна обрабатываться определением вашей CSS-анимации — через animation / transition delay и/или используя animationend или transitionend для добавления следующего CSS для анимации.

Отключение анимации или всех анимаций

С нативными CSS-анимациями, если нужно отключить указанные анимации, есть несколько вариантов.

  1. Создайте пользовательский класс, который принудительно задаёт animation и transition в none.
.no-animation {
  animation: none !important;
  transition: none !important;
}

Применение этого класса к элементу предотвращает запуск любой анимации на этом элементе. Можно также ограничить область действия всем DOM или секцией DOM, чтобы обеспечить это поведение. Однако это предотвращает срабатывание animation events. Если вы ждёте animation events для удаления элемента, это решение не сработает. Обходной путь — задать duration в 1 миллисекунду.

  1. Используйте media query prefers-reduced-motion, чтобы гарантировать, что анимации не воспроизводятся для пользователей, предпочитающих меньше анимации.

  2. Не добавляйте animation-классы программно

Callbacks анимаций

Пакет animations предоставлял callbacks на случай, если нужно что-то сделать, когда анимация завершилась. У нативных CSS-анимаций тоже есть эти callbacks.

OnAnimationStart
OnAnimationEnd
OnAnimationIteration
OnAnimationCancel

OnTransitionStart
OnTransitionRun
OnTransitionEnd
OnTransitionCancel

Web Animations API имеет много дополнительной функциональности. Посмотрите документацию, чтобы увидеть все доступные animation API.

ПРИМЕЧАНИЕ: Учитывайте проблемы bubbling с этими callbacks. Если анимируете детей и родителей, события всплывают от детей к родителям. Рассмотрите остановку propagation или просмотр деталей события, чтобы определить, что вы реагируете на желаемый event target, а не на событие, всплывающее от дочернего узла. Можно проверить свойство animationname или свойства, которые transition'ятся, чтобы убедиться, что у вас правильные узлы.

Сложные последовательности

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

Таргетинг конкретных элементов

В пакете animations можно было таргетировать конкретные элементы с помощью функции query(), чтобы находить элементы по имени CSS-класса, аналогично document.querySelector(). В мире нативных CSS-анимаций это не нужно. Вместо этого можно использовать CSS-селекторы для таргетинга подклассов и применять любой желаемый transform или animation.

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

Stagger()

Функция stagger() позволяла задерживать анимацию каждого элемента в списке на указанное время, чтобы создать cascade-эффект. Это поведение можно воспроизвести в нативном CSS, используя animation-delay или transition-delay. Вот пример того, как может выглядеть такой CSS.

С пакетом Animations

С нативным CSS

Параллельные анимации

Пакет animations имеет функцию group() для одновременного воспроизведения нескольких анимаций. В CSS у вас полный контроль над timing анимации. Если определено несколько анимаций, можно применить их все сразу.

.target-element {
  animation:
    rotate 3s,
    fade-in 2s;
}

В этом примере анимации rotate и fade-in запускаются одновременно.

Анимация элементов переупорядочиваемого списка

Переупорядочивание элементов в списке работает из коробки с помощью ранее описанных техник. Дополнительная специальная работа не требуется. Элементы в цикле @for будут корректно удаляться и добавляться заново, что запустит анимации с использованием @starting-styles для entry-анимаций. Альтернативно можно использовать animate.enter для того же поведения. Используйте animate.leave для анимации элементов при удалении, как видно в примере выше.

С пакетом Animations

С нативным CSS

Миграция использований AnimationPlayer

Класс AnimationPlayer позволяет получать доступ к анимации для более продвинутых вещей — pause, play, restart и finish анимации через код. Всё это также можно обработать нативно.

Можно получить анимации с элемента напрямую через Element.getAnimations(). Это возвращает массив каждого Animation на этом элементе. API Animation позволяет делать гораздо больше, чем предлагал AnimationPlayer из пакета animations. Отсюда можно cancel(), play(), pause(), reverse() и многое другое. Этот нативный API должен предоставить всё необходимое для управления анимациями.

Route Transitions

Можно использовать view transitions для анимации между маршрутами. См. Route Transition Animations Guide, чтобы начать.