Улучшения API веб-анимации в Chromium 84

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

Опубликовано: 27 мая 2020 г.

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

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

В то время как Firefox и Safari уже реализовали полный набор функций , Chromium 84 добавляет в Chrome и Edge множество ранее не поддерживаемых функций, обеспечивая межбраузерную совместимость.

API веб-анимации впервые появился в Chromium в версии 36 в июле 2014 года. Теперь спецификация будет завершена в версии 84, которая выйдет в июле 2020 года.
Долгая история API веб-анимации в Chromium.

Начиная

Создание анимации с использованием API веб-анимации должно показаться вам очень знакомым, если вы использовали правила @keyframe . Сначала вам нужно создать объект ключевого кадра. Как это может выглядеть в CSS:

@keyframes openAnimation {
  0% {
    transform: scale(0);
  }
  100% {
    transform: scale(1);
  }
}

в JavaScript будет выглядеть так :

const openAnimation = [
  { transform: 'scale(0)' },
  { transform: 'scale(1)' },
];

Где вы устанавливаете параметры анимации в CSS:

.modal {
  animation: openAnimation 1s 1 ease-in;
}

вы бы установили в JS:

document.querySelector('.modal').animate(
    openAnimation, {
      duration: 1000, // 1s
      iterations: 1, // single iteration
      easing: 'ease-in' // easing function
    }
);

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

За пределами element.animate()

Однако с обновлением API веб-анимации больше не ограничивается анимацией, созданной с помощью element.animate() . Мы также можем управлять анимацией и переходами CSS.

getAnimations() — это метод, который возвращает все анимации элемента независимо от того, был ли он создан с помощью element.animate() или с использованием правил CSS (CSS-анимация или переход). Вот пример того, как это выглядит:

Сначала вы "get" ключевые кадры для перехода, чтобы определить, откуда мы переходим. Затем вы создаете две новые анимации непрозрачности, включающие эффект плавного затухания. Как только плавное затухание завершится, вы удалите копию.

Как организовать анимацию с помощью обещаний

В Chromium 84 теперь есть два метода, которые можно использовать с промисами: animation.ready и animation.finished .

  • animation.ready позволяет дождаться вступления в силу ожидающих изменений (то есть переключения между методами управления воспроизведением, такими как воспроизведение и пауза).
  • animation.finished предоставляет средства выполнения пользовательского кода JavaScript после завершения анимации.

Продолжая наш пример, создайте оркестрованную цепочку анимации с animation.finished . Здесь у вас есть вертикальное преобразование ( scaleY ), за которым следует горизонтальное преобразование ( scaleX ), за которым следует изменение непрозрачности дочернего элемента:

Применение преобразований и непрозрачности к открывающемуся модальному элементу. См. демо на Codepen
const transformAnimation = modal.animate(openModal, openModalSettings);
transformAnimation.finished.then(() => { text.animate(fadeIn, fadeInSettings)});

Мы связали эти анимации в цепочку с помощью animation.finished.then() перед выполнением следующего набора анимаций в цепочке. Таким образом, анимация отображается по порядку, и вы даже применяете эффекты к разным целевым элементам с разными наборами параметров (например, скоростью и легкостью).

В CSS это было бы сложно воссоздать, особенно при применении уникальных, но последовательных анимаций к нескольким элементам. Вам придется использовать @keyframe , определить правильные проценты времени для размещения анимации и использовать animation-delay перед запуском анимации в последовательности.

Пример: воспроизведение, пауза и обратный ход.

То, что может открыться, должно закрыться! К счастью, начиная с Chromium 39 , API веб-анимации предоставил нам возможность воспроизводить, приостанавливать и реверсировать анимацию.

Вы можете взять показанную ранее анимацию и придать ей плавную обратную анимацию при повторном нажатии кнопки с помощью .reverse() . Таким образом, вы можете создать более плавное и контекстуальное взаимодействие для нашего модального окна.

Пример открытия и закрытия модального окна при нажатии кнопки. См. демо-версию Glitch

Что вы можете сделать, так это создать две анимации, ожидающие воспроизведения ( openModal и встроенное преобразование непрозрачности), а затем приостановить одну из анимаций, отложив ее до завершения другой. Затем вы можете использовать обещания, чтобы дождаться завершения каждого из них, прежде чем играть. Наконец, вы можете проверить, установлен ли флаг, а затем обратить каждую анимацию вспять.

Пример. Динамическое взаимодействие с частичными ключевыми кадрами.

Пример ретаргетинга, когда щелчок мыши перемещает анимацию в новое место. См. демо-версию Glitch
selector.animate([{transform: `translate(${x}px, ${y}px)`}],
    {duration: 1000, fill: 'forwards'});

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

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

Улучшения производительности за счет сменной анимации

При создании анимации на основе событий, таких как 'mousemove' , каждый раз создается новая анимация, которая может быстро занимать память и снижать производительность. Чтобы решить эту проблему, в Chromium 83 были представлены заменяемые анимации, позволяющие осуществлять автоматическую очистку, при которой готовые анимации помечаются как заменяемые и автоматически удаляются, если они заменяются другой готовой анимацией. Рассмотрим следующий пример:

След кометы оживляется при движении мыши. См. демо-версию Glitch
elem.addEventListener('mousemove', evt => {
  rectangle.animate(
    { transform: translate(${evt.clientX}px, ${evt.clientY}px) },
    { duration: 500, fill: 'forwards' }
  );
});

Каждый раз, когда мышь перемещается, браузер пересчитывает положение каждого шарика на следе кометы и создает анимацию для этой новой точки. Браузер теперь умеет удалять старые анимации (включив замену), когда:

  1. Анимация закончена.
  2. Существует одна или несколько анимаций выше в составном порядке, которые также завершены.
  3. Новые анимации анимируют те же свойства.

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

Есть несколько дополнительных способов еще больше улучшить управление анимацией:

  • animation.replaceState() предоставляет средства отслеживания того, является ли анимация активной, сохраненной или удаленной.
  • animation.commitStyles() обновляет стиль элемента на основе базового стиля вместе со всеми анимациями элемента в составном порядке.
  • animation.persist() помечает анимацию как незаменяемую.

Более плавная анимация с составными режимами

С помощью API веб-анимации теперь вы можете установить составной режим вашей анимации, то есть они могут быть аддитивными или накопительными, в дополнение к режиму «замены» по умолчанию. Комбинированные режимы позволяют разработчикам создавать отдельные анимации и контролировать объединение эффектов. Теперь поддерживаются три составных режима: 'replace' (режим по умолчанию), 'add' и 'accumulate' .

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

Демонстрация, показывающая составные режимы по умолчанию, добавления и накопления. См. демо-версию Glitch

В составном режиме 'replace' по умолчанию окончательная анимация заменяет свойство преобразования и заканчивается в rotate(360deg) scale(1.4) . Для 'add' Composite добавляет вращение и умножает масштаб, в результате чего получается окончательное состояние rotate(720deg) scale(1.96) . 'accumulate' объединяет преобразования, в результате чего получается rotate(720deg) scale(1.8) . Дополнительные сведения о тонкостях этих составных режимов см. в перечислениях CompositeOperation и CompositeOperationOrAuto из спецификации Web Animations.

Взгляните на следующий пример элемента пользовательского интерфейса:

Упругое раскрывающееся меню, к которому применены две составные анимации. См. демо-версию Glitch

Здесь объединены две top анимации. Первый — это макроанимация, которая перемещает раскрывающийся список на всю высоту самого меню в виде эффекта слайд-шоу от верхней части страницы, а второй, микроанимация, применяет небольшой отскок при перемещении. ударяется о дно. Использование композитного режима 'add' обеспечивает более плавный переход.

const dropDown = menu.animate(
    [
      { top: `${-menuHeight}px`, easing: 'ease-in' },
      { top: 0 }
    ], { duration: 300, fill: 'forwards' });

  dropDown.finished.then(() => {
    const bounce = menu.animate(
      [
        { top: '0px', easing: 'ease-in' },
        { top: '10px', easing: 'ease-out' },
        { ... }
      ], { duration: 300, composite: 'add' });
  });

Что будет дальше с API веб-анимации

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