Знакомимся с Web Animations API

Автор оригинала: Charlie Gerard
  • Перевод
Доброго времени суток, друзья!

Веб 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

Благодарю за внимание.

Похожие публикации

AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 2

    –1
    Интересно, сколько еще должно пройти лет, что бы в вебе снова изобрели flash?
      0

      Странный способ установления зависимости установки длительности анимации

      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

      Самое читаемое