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

http://updates.html5rocks.com/2014/05/Web-Animations---element-animate-is-now-in-Chrome-36
  • Перевод
Анимация в вебе была одна из областей 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 анимации. Мы видим только один способ сделать это правильно: дать разработчикам попробовать и посмотреть, что они скажут.

Спасибо Эдди Османи и Максу Хейнрицу за их помощь в написании этого поста
  • +25
  • 20,8k
  • 9
Поделиться публикацией

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

    +3
    Web Animations это отличная вещь, особенно, что наконец-то появился контроль над анимациями: пауза, ускорение и т.д.
    Возможно интересно
    У нас есть библиотека на базе CSS3 Transitions с довольно интересным синтаксисом: property | ?fom > to | easing duration delay . Пример модели:

    mask.animate(document.body, {
        model: 'transform | > translateX(10%) | 1s ease-in',
        next: {
        	model: [
        		'transform | > scale(0.5) rotate(360deg) | 400ms linear 400ms',
        		'background-color | yellow > cyan | 4s'
        	],
        	next: 'display | > none'
        }
    }, console.log.bind(console, "done"));
    



      +11
      Ох уж этот снег на сайтах, столько негативных эмоций сразу нахлынуло. Каждую зиму одно и тоже, а этой зимой с нативной реализацией в хроме!
        0
        А если кто-то хочет иметь производительные анимации и при этом все делать в привычном jQuery.animate синтаксисе — есть Velocity.js.
          0
          Демо снежинок можно посмотреть в двух исполнениях: на нативной реализации и на реализации с помощью полифила.
          Странно, что в демках находятся просто 2 гифки. С таким же успехом их можно было б сюда вставить.

          Как бы то нибыло, существует полифил
          Этот полифил по крайне в данный момент не детектит поддержку свойства, а сразу записывает в прототип (что очень странно) со всеми вытекающими оттуда последствиями. Кроме того создает в глобальном пространстве имен всякий левак в виде таких функций, как Animation, AnimationEffect и пр. То есть сейчас это совсем не полифил, а функция-подражатель. И еще нету поддержки пока что актуального ИЕ8. И ладно бы просто поддержки: из-за многочисленных defineProperty в ИЕ8 будут js-ошибки.
            0
            Не особо понял, где вы взяли 2 гифки, т.к. по обоим ссылкам на jsbin лежат полноценные примеры.

            Этот полифил по крайне в данный момент не детектит поддержку свойства, а сразу записывает в прототип

            Дарёному коню… Вы всегда можете попробовать сделать лучше или не использовать его вовсе.
            Проблема IE8 с defineProperty решается modernizr'ом или аналогичным решением. В случае modernizr'a, ошибок в IE8 нет.
              0
              Ну я зашел, в фаирбаге посмотрел, у фона body проставлен анимированный гиф. Может я что то не понял.

              > Дарёному коню… Вы всегда можете попробовать сделать лучше или не использовать его вовсе.

              Не понимаю, при чем тут «сперва добейся», «дареный конь»? Может автору, который провел анализ (http://habrahabr.ru/post/177115/) angular, backbone и пр. тоже сперва написать свою либу с блекджеком, прежде чем указывать на недостатки тех или иных либ? Ну и вообще всем, кто ищет недостатки в либах.

              > Проблема IE8 с defineProperty решается modernizr'ом или аналогичным решением. В случае modernizr'a, ошибок в IE8 нет.

              Ну ок, жс-ошибки вы победите, но еще придется писать альтернативный код анимации, что не очень прикольно поддерживать. Ну да хрен с ним с ИЕ8, в ИЕ9 тоже жс-ошибки, а ведь он не такой уж и старый. В ИЕ10 не проверял.
                0
                Не понимаю, при чем тут «сперва добейся», «дареный конь»? Может автору, который провел анализ (http://habrahabr.ru/post/177115/) angular, backbone и пр. тоже сперва написать свою либу с блекджеком, прежде чем указывать на недостатки тех или иных либ? Ну и вообще всем, кто ищет недостатки в либах.

                Обычно на больших проектах так и происходит: вы выбираете каркас для своего приложения, будь то backbone, angular или что-либо ещё, и перепиливаете его под свои нужды, чтобы заткнуть «дырки» в реализации библиотеки/фрейморка.

                Ну ок, жс-ошибки вы победите, но еще придется писать альтернативный код анимации, что не очень прикольно поддерживать

                По-прежнему не понимаю, о чём вы говорите: есть полифил (уже неоднократно об этом говорили), которые реализует подобную функциональность для устаревших/устаревающих браузеров (посмотрите подробную информацию по IE: www.w3schools.com/browsers/browsers_stats.asp). Тем более, когда это станет стандартом, можно будет не заботиться о IE8, и, возможно, даже IE9.
                  0
                  > Обычно на больших проектах так и происходит: вы выбираете каркас для своего приложения, будь то backbone, angular или что-либо ещё, и перепиливаете его под свои нужды, чтобы заткнуть «дырки» в реализации библиотеки/фрейморка.

                  Ну собстна, я и не призывал линчевать авторов «полифила», а указал на особенности его реализации. Не понимаю, зачем мне для этого сначала нужно что то свое более лучшее писать. Разумеется, кто захочет воспользоваться сам решит важен ли ему ИЕ8-9.

                  > По-прежнему не понимаю, о чём вы говорите
                  Я не знаю как проще объяснить. Я говорю о том, что конкретно этот полифил не получится здесь и сейчас использовать для ИЕ9. Только и всего.

                  В целом еще о полифиле: т.к. он выпиливает нативный .animate(), возможность его использования вместо greensock кажется очень сомнительной, ведь по сути этот тот же гринсок, ток гринсок еще умеет для ие8. Возможно это кому то будет полезным знать. Хотя вру, гринсок это другое. Но как минимум еще есть zepto, который как раз через css анимирует.
            0
            удалено

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

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