Pull to refresh

Веб анимации — element.animate() уже в Chrome 36

Reading time 4 min
Views 24K
Original author: Brendan Kenny
Анимация в вебе была одна из областей JavaScript, но сейчас, когда мир пересел на мобильные устройства, анимация переместилась на CSS. Это позволило нам использовать декларативный синтаксис при описании анимации, а браузеру производить оптимизацию. В погоне за 60fps (60 кадров в секунду) на мобильных устройствах, вам будет полезно знать все тонкости и нововведения, касающиеся механизмов эффективного отображения анимации в ваших браузерах.

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

Веб анимации призваны ответить на этот зов, и первая их часть уже была включена в релиз Chrome 36 в виде element.animate(). Эта новая функциональность позволяет вам создавать анимации на чистом JavaScript и при этом получать производительность, как при использовании CSS анимации или переходов (на самом деле уже с 34-й версии Chrome все описанные выше методы запускаются через движок веб анимаций).

Синтаксис весьма простой, и, скорее всего, он покажется вам знакомым, если вы когда-либо писали CSS переходы (transitions) или анимацию:

element.animate([
  {cssProperty: value0},
  {cssProperty: value1},
  {cssProperty: value2},
  //...
], {
    duration: timeInMs,
    iterations: iterationCount,
    delay: delayValue
});


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

Например, для «Отслеживания Санты» в прошлом году, мы хотели видеть плавно падающие снежинки, и мы решили делать анимацию посредством CSS. Так вот, этот element.animate может быть ничуть не менее производительным.

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

Поэтому, в следующем примере мы применили уже знакомый нам подход:

snowFlake.style.transform = 'translate(' + snowLeft + 'px, -100%)';
// Ожидание кадра
snowFlake.offsetWidth;
snowFlake.style.transitionProperty = 'transform';
snowFlake.style.transitionDuration = '1500ms';
snowFlake.style.transform = 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)';


Фишка в комментарии «ожидание кадра». Для того, чтобы обеспечить успешное начало перемещения, браузер должен знать, что элемент находится в стартовой позиции, и есть несколько способов в этом убедиться. Один из самый часто используемых — прочитать одно из свойств объекта, тем самым вызвав пересчет разметки страницы, тем самым подтверждая, что элемент имеет стартовую позицию перед началом перемещения к конечной. Использование этого метода позволяет вам еще раз порадоваться за то, что вы знаете основы работы механизма рендеринга в браузере.

Синтаксис, как мы видим, настолько прозрачен, что больше и не придумаешь:

snowFlake.animate([
  {transform: 'translate(' + snowLeft + 'px, -100%)'},
  {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);


Но так же мы можем указать множество разнообразных настроек. Так же как и CSS анимации, Веб анимации могут быть отложены и итерированы.

snowFlake.animate([
  {transform: 'translate(' + snowLeft + 'px, -100%)'},
  {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], {
  duration: 1500,
  iterations: 10,
  delay: 300
});


Объект AnimationPlayer


element.animate() возвращает объект AnimationPlayer, важность которого растет пропорционально количеству запущенных анимаций на странице. И JavaScript, и CSS анимации будут ассоциированы с AnimationPlayer'ами, позволяя им объединяться разными полезными и интересными способами.

Сейчас, AnimationPlayer имеет две функциональности, и обе очень полезные. Вы можете отменить анимацию в любой момент времени используя AnimationPlayer.cancel():

var player = snowFlake.animate([
  {transform: 'translate(' + snowLeft + 'px, -100%)'},
  {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);
// Но вдруг, раньше, чем через 1.5 секунды, я передумал.
player.cancel();


И, к слову, тем, кто привык использовать CSS анимации и переходы, я хочу сказать, что Веб Анимации всегда вызывают события по окончанию:

var player = snowFlake.animate([
  {transform: 'translate(' + snowLeft + 'px, -100%)'},
  {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);
player.onfinish = function(e) {
  console.log('per aspera ad terra!');
}


Попробуйте!


Вся эта функциональность находится под капотом Chrome 36, релиз которого уже произошел на днях! Если вы хотите попробовать, сделайте это на нативной реализации в Chrome 36. Как бы то нибыло, существует полифил, который добавляет данную функциональность во все новейшие браузеры.

Демо снежинок можно посмотреть в двух исполнениях: на нативной реализации и на реализации с помощью полифила.

Поделитесь с нами своими соображениями


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

Спасибо Эдди Османи и Максу Хейнрицу за их помощь в написании этого поста
Tags:
Hubs:
+25
Comments 9
Comments Comments 9

Articles