CSS-live.ru

Руководство по Web Animations API — часть 1: создание базовой анимации

Перевод статьи Web Animations API Tutorial Part 1: Creating a Basic Animation с сайта danielcwilson.com, опубликовано на css-live.ru с разрешения автора — Дэна Уилсона (твиттер — @dancwilson).

Это первая часть из серии вводных/учебных статей про Web Animations API, который вот-вот появится в браузерах. Если у вас есть мысли/вопросы, вы заметили, что я неправильно истолковал спецификацию, или хотите обсудить со мной что-то конкретное в будущих статьях, то обращайтесь ко мне в Twitter, @dancwilson.

Мы окинули беглым взглядом Web Animations API, но так и не добрались до какой-либо конкретики… так что давайте приступим к этому прямо сейчас.

WAAPI даёт больше контроля, чем вы, возможно, получали от CSS-анимаций, но давайте на время оставим это и сначала разберёмся с основами: как мне создать базовую анимацию при помощи этого API?

Создание ключевых кадров анимации

Если вы работали с CSS-переходами и/или анимациями, то это будет вам знакомо.

var player = document.getElementById('toAnimate').animate([
    { transform: 'scale(1)', opacity: 1, offset: 0 },
    { transform: 'scale(.5)', opacity: .5, offset: .3 },
    { transform: 'scale(.667)', opacity: .667, offset: .7875 },
    { transform: 'scale(.6)', opacity: .6, offset: 1 }
  ], {
    duration: 700, //миллисекунды
    easing: 'ease-in-out', //'linear', кривая Безье, и т.д.
    delay: 10,  //миллисекунды
    iterations: Infinity, //или число
    direction: 'alternate', //'normal', 'reverse', и т.д.
    fill: 'forwards' //'backwards', 'both', 'none', 'auto'
  });

Сравните с такой же анимацией на CSS:

@keyframes emphasis {
  0% {
    transform: scale(1); 
    opacity: 1; 
  }
  30% {
    transform: scale(.5); 
    opacity: .5; 
  }
  78.75% {
    transform: scale(.667); 
    opacity: .667; 
  }
  100% {
    transform: scale(.6);
    opacity: .6; 
  }
}
#toAnimate {
  animation: emphasis 700ms ease-in-out 10ms infinite alternate forwards;
}

Разберем этот код по кусочкам:

var player = document.getElementById('toAnimate').animate()

Анимации вернут объект AnimationPlayer, который позволит в будущем творить забавные вещи, так что вам, скорее всего, понадобится переменная, чтобы ссылаться на него. Находим наш анимируемый элемент (здесь просто по document.getElementById) и взываем функцию animate. Эта функция появилась в спецификации недавно, так что либо проверяйте ее на наличие/поддержку перед использованием, либо подключите полифилл.

Функция animate принимает два параметра, массив объектов KeyframeEffect и опции AnimationEffectTimingProperties. По сути первый параметр соответствует тому, что в CSS вы написали бы внутри правила @keyframes, а второй — значениям в свойствах animation-* (или в сокращённой записи animation, как в предыдущем примере) в CSS-коде. Основное преимущество здесь в том, что мы можем использовать переменные и заново использовать один и тот же KeyframeEffect, тогда как в CSS нам пришлось бы довольствоваться значениями, объявленными заранее.

var player = document.getElementById('toAnimate').animate([
    { transform: 'scale(1)', opacity: 1 },
    { transform: 'scale(.5)', opacity: .5 },
    { transform: 'scale(.667)', opacity: .667 },
    { transform: 'scale(.6)', opacity: .6 }
  ]);

Для каждого KeyframeEffect мы указываем не смещение в процентах, как в CSS, а десятичное значение offset от 0 до 1. Хотя это необязательно, и если значения не указаны, то они распределятся равномерно (к примеру, если их три штуки, у первого смещение будет равно 0, у второго — .5, а у третьего — 1). Также можно указать свойство easing, которое соответствует свойству animation-timing-function в CSS. Значения для каждого свойства соответствуют тем, которые мы указываем в JavaScript при помощи element.style, поэтому opacity будет числом, а transform ожидает строку.

var player = document.getElementById('toAnimate').animate([], {
    duration: 700, //milliseconds
    easing: 'ease-in-out', //'linear', a bezier curve, etc.
    delay: 10, //milliseconds
    iterations: Infinity, //or a number
    direction: 'alternate', //'normal', 'reverse', etc.
    fill: 'forwards' //'backwards', 'both', 'none', 'auto'
  });

Временные свойства соответствуют свойствам CSS-анимации, хотя имена иногда не совпадают. В первом примере кода рассматриваются основные опции.

Вот пример с применением полифилла (но если вы просматриваете в последней версии Chrome, там должна использоваться настоящая браузерная реализация). Серые блоки из первой колонки анимированы при помощи WAAPI, а красные во второй колонке — при помощи CSS keyframes.

В следующей серии…

Теперь, когда мы знаем, как создавать такую же анимацию, как и в CSS, мы начнём изучать объект AnimationPlayer, который возвращает функция анимации. Именно здесь мы увидим реальные возможности и улучшения.

Поглядите остальные статьи из этой серии:

P.S. Это тоже может быть интересно:

5 комментариев

  1. Я правильно понял :
    каждый шаг анимации — это отдельный объект в массиве.?
    Я попробовал сделать , что-то типа : elem.animate([{opacity:[0,1]},{heigth:[«10px»,»100px»]}], 1000). Это действует при одном свойстве , допустим opacity, а для всех остальных интерпретации это — один шаг — один объект :([{opacity:0, heigth: «10px»},{opacity:1,heigth:»100px»}], 1000)

    1. Да, каждый шаг, вернее, каждый ключевой кадр, со всеми значениями свойств, какими они должны быть в соотв. момент — отдельный объект в массиве. Запись ключевого кадра {opacity:[0,1]} у меня в канареечном Хроме 58 выдает ошибку «Failed to execute ‘animate’ on ‘Element’: Lists of values not permitted in array-form list of keyframes».

        1. Понял:). Есть две формы записи: либо объект вида «свойство1 — массив значений, свойство2 — массив значений…», либо массив объектов вида «свойство — значение». Т.е. записи

          elem.animate(
            {
              opacity: [0,1],
              height: ["10px","100px"]
            },
            1500)
          // и
          elem.animate(
            [
              { opacity: 0, height: "10px" },
              { opacity: 1, height: "100px" }
            ],
            1500)

          эквивалентны и обе работают. А код из первого комментария не работал из-за лишних (для первого варианта записи) квадратных скобок.

          1. Ах вот оно что. Мне чуть не хватило смекалки , что бы дойти до этого , либо терпения , что бы найти в документации .
            Крайне благодарен тем не менее :)

Оставить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

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