Доброго времени суток, друзья!
Представляю Вашему вниманию перевод статьи Charlie Gerard «Exploring the Web Animations API».
Знакомимся с Web Animations API
Веб API постоянно эволюционируют. Некоторые из них, такие как Console или Canvas, хорошо поддерживаются всеми браузерами, другие по-прежнему находятся на стадии разработки.
Одним из API, находящимся на стадии разработки, является Web Animations API или WAAPI. Несмотря на то, что первый вариант спецификации был опубликован в 2012 году, а сам API впервые реализован в браузерах Firefox и Chrome в 2014 году, я узнала о нем совсем недавно (я тоже раньше о нем не слышал — прим.пер.).
Он позволяет разработчикам работать с CSS анимацией средствами JavaScript. Его синтаксис похож на синтаксис традиционной CSS анимации, но имеет некоторые особенности, которые облегчают разработчикам создание и изменение анимации.
Давайте рассмотрим этот API на простом примере.
Ниже мы видим вращающийся квадрат, цвет которого меняется с каждым поворотом.

CSS-код может выглядеть так:
#cube { width: 40px; height: 40px; margin: 50%; background-color: pink; animation: rotateCube 1s infinite; } @keyframes rotateCube { 0% { transform: rotate(0deg); } 30% { background-color: purple; } 100% { transform: rotate(180deg); } }
Теперь сделаем тоже самое с помощью WAAPI.
Создание анимации
Все начинается с создания объекта Keyframes, содержащего информацию, аналогичную той, которая содержится в директиве @keyframes нашего CSS:
let cubeRotating = [ {transform: 'rotate(0deg)', backgroundColor: 'pink'}, {backgroundColor: 'purple', offset: 0.3}, {transform: 'rotate(180deg)', backgroundColor: 'pink'} ]
Мы видим два главных отличия:
- Нам необходимо добавить backgroundColor в другие шаги.
- Нам не нужно определять время выполнения каждого шага в процентах.
WAAPI автоматически делит анимацию на равные части по количеству ключей, поэтому в нашем случае цвет фона будет меняться примерно на половине анимации.
Однако мы хотим, чтобы это происходило на 30%, поэтому мы добавляем во второй шаг свойство offset со значением 0.3.
Необходимо запомнить одну важную вещь: в объекте Keyframes должно быть как минимум два ключа. В противном случае, будет выброшена ошибка NotSupportedError.
Далее создается объект, содержащий свойства анимации, отвечающие за продолжительность и количество повторов:
let cubeTiming = { duration: 1000, iterations: Infinity }
Продолжительность анимации устанавливается в миллисекундах.
Вместо «infinite» мы используем ключевое слово «Infinity».
Наконец, для запуска анимации мы используем метод Element.animate:
document.getElementById('cube').animate( cubeRotating, cubeTiming )
Существует еще несколько вариантов синтаксиса. Примеры можно посмотреть здесь.
Но это еще не все. Дело в том, что с помощью WAAPI мы может управлять воспроизведением анимации!
Управление воспроизведением анимации
Вызов метода animate запускает анимацию немедленно, но это не всегда то, чего мы хотим. Поэтому мы можем вызывать методы pause и play для остановки и запуска анимации, соответственно:
let cubeAnimation = document.getElementById('cube').animate( cubeRotating, cubeTiming ) cubeAnimation.pause() document.body.onclick = () => cubeAnimation.play()
В нашем примере мы работаем с одной анимацией, но вы вполне можете добавить на страницу несколько «анимаций» и управлять ими, как заблагорассудится.
Среди доступным методов WAAPI также есть методы finish, cancel и reverse.
Также мы можем управлять скоростью воспроизведения анимации:
let cubeAnimation = document.getElementById('cube').animate( cubeRotating, cubeTiming ) document.body.onclick = () => cubeAnimation.playbackRate *= 1.5
Данный код заставляет квадрат вращаться быстрее при клике.

До сих пор мы изучали, как создавать одну анимацию и управлять ее воспроизведением. Другой возможностью WAAPI является доступ ко всем анимациям сразу.
Управление множеством анимаций
У WAAPI есть метод getAnimations, позволяющий получить доступ ко всем созданным анимациям.
Допустим, мы хотим замедлить все анимации, имеющиеся на странице, если пользователь включил prefers-reduced-motion (CSS медиа функция prefers-reduced-motion может использоваться для определения того, запросил ли пользователь, чтобы ОС минимизировала количество анимации или движения, которые она использует — прим. пер.):
const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)') if(mediaQuery.matches){ document.getAnimations().forEach(animation => { animation.playbackRate *= 0.5 }) }
В примере выше мы ищем медиа функцию prefers-reduced-motion и, если ее значение равняется reduce, получаем все анимации на странице и уменьшаем скорость их воспроизведения наполовину.
Эта одна из тех вещей, которые делают WAAPI очень полезной. Мы можем вносить изменения в несколько анимаций посредством изменения одного свойства.
Зависимости
Еще одной интересной возможностью WAAPI является возможность определить зависимость свойств одной анимации от свойств другой.
Например, если у нас есть два квадрата, и мы хотим, чтобы второй вращался в два раза быстрее первого, мы можем сделать это двумя способами.
Первый способ:
let cube1Animation = document.getElementById('cube').animate( cubeRotating, { duration: 1000, iterations: Infinity } ) let cube2Animation = document.getElementById('cube2').animate( cubeRotating, { duration: 500, iterations: Infinity } )
Время анимации первого квадрата составляет 1 секунду, второго — 500 миллисекунд.
Однако при таком подходе, когда мы меняем время анимации первого квадрата, нам нужно сделать тоже самое у второго квадрата.
Вы понимаете, насколько это станет сложным при наличии множества анимаций или большого количества анимированных объектов.
Лучшим способом решить нашу задачу является установление зависимости вращения второго квадрата от первого:
let cube1Animation = document.getElementById('cube').animate( cubeRotating, { duration: 1000, iterations: Infinity } ) let cube2Animation = document.getElementById('cube2').animate( cubeRotating, { duration: cube1Animation.effect.timing.duration / 2, iterations: Infinity } )
Таким образом, мы используем время анимации первого квадрата для определения времени анимации второго квадрата. Теперь при изменении времени анимации первого квадрата, второй всегда будет вращаться в два раза быстрее!

Производительность
Говоря о производительности, я не заметила особой разницы между использованием CSS и WAAPI. Но это может быть связано с простотой моего примера.
Одним важным преимуществом WAAPI по сравнению с другими способами создания анимации в JS является то, что он выполняется в отдельном потоке, что позволяет основному потоку «забыть» про анимацию и заниматься остальным кодом.
Поддержка браузеров
В настоящее время WAAPI находится в статусе черновика и частично поддерживается в последних версиях Firefox и Chrome, а также в основных мобильных браузерах.
Частичная поддержка означает, что браузеры поддерживают такие методы как play, pause, reverse, finish и playbackRate, но не поддерживают getAnimations.

Существует полифил для работы WAAPI во всех браузерах.
На этом у меня все!
Дополнительная литература:
Using the Web Animations API
Web Animations API examples
Great series «Let’s talk about the Web Animations API» by Dan Wilson
Благодарю за внимание.
ссылка на оригинал статьи https://habr.com/ru/post/486454/
Добавить комментарий