Как получилось так, что Javascript анимация быстрее и лучше CSS переходов? И как стало возможным, что релизы медиа-мобильных сайтов у Adobe и Google конкурируют с нативными приложениями?

 

В этой статье изложен детальный разбор, почему библиотеки Javascript DOM анимации, такие как Velocity.js и GSAP более производительные, чем jQuery и CSS анимация.

 

Щелкните по картинке и оцените возможности Javascript:

 

velo2

 

jQuery

Начнем с основ: Javascript и jQuery были ложно объединены. Javascript анимация быстрая. jQuery замедляет анимацию . Все из-за того, что анимация не была целью проекта jQuery и в нем не заложен мощный производительный движок, хотя jQuery является достаточно мощной библиотекой:

 

 

Примеры

Чтобы избежать подтормаживания макета достаточно просто сгруппировать вместе DOM-запросы и DOM-апдейты:

var currentTop, currentLeft;

/* With layout thrashing. */
currentTop = element.style.top; /* QUERY */
element.style.top = currentTop + 1; /* UPDATE */

currentLeft = element.style.left; /* QUERY */
element.style.left = currentLeft + 1; /* UPDATE */

/* Without layout thrashing. */
currentTop = element.style.top; /* QUERY */
currentLeft = element.style.left; /* QUERY */

element.style.top = currentTop + 1; /* UPDATE */
element.style.left = currentLeft + 1; /* UPDATE */

 

 

Плавность анимации зависит от частоты кадров. Частота кадров измеряется в «кадрах в секунду» (FPS – Frame Per Second). Фильмы и видео обычно делают с частотой 24 fps – 30 fps. Чем больше это число, тем более гладкой кажется анимация. С другой стороны – чем больше FPS, тем больше нужно ресурсов процессора, что может привести к подвисанию и пропуску кадров. Т.к. у большинства экранов частота обновления составляет 60 Гц – то и fps, к которому надо стремится должен быть равен 60-ти.

 

Исходя из этого, можно посчитать идеальный интервал1000ms / 60(fps) = 16.7ms

Т.е. setInterval(step, 17);

 

И что из этого следует?

  1. setTimeout() и setInterval() не обращают внимание на то, что еще происходит в браузере. Страница, на которой происходит анимация, может находится на неактивной вкладке браузера. И при этом все равно будут использоваться ресурсы процессора. На данный момент только Chrome делает интервал анимации равным 1fps на скрытых вкладках.
  2. SetTimeout()иsetInterval()требуют перерисовки страницы не тогда, когда это делает компьютер (а он делает это регулярно). Это означает, что браузер должен синхронизировать вашу анимацию с обновлением всего экрана, и если ее частота не синхронизирована с обновлением всего экрана, это может потребовать больше вычислительной мощности. А это загрузка процессора, расход батареи мобильных устройств и дерганная анимация.
  3. Самая большая проблема настает, когда нужно анимировать несколько элементов сразу. Можно попытаться все это синхронизировать, но это станет очередным кошмаром в случае разноплановой анимации, происходящей одновременно.

 

 

Вместо этого, разработчики Mozilla предложили использовать функцию requestAnimationFrame (RAF), которая не требует значительной переработки существующего кода. Можно сравнить базовую реализацию RAF и setInterval:

var startingTop = 0;

/* setInterval: Runs every 16ms to achieve 60fps (1000ms/60 ~= 16ms). */
setInterval(function() {
	/* Since this ticks 60 times a second, we divide the top property's increment of 1 unit per 1 second by 60. */
	element.style.top = (startingTop += 1/60);
}, 16);

/* requestAnimationFrame: Attempts to run at 60fps based on whether the browser is in an optimal state. */
function tick () {
    element.style.top = (startingTop += 1/60);
}

window.requestAnimationFrame(tick);

 

 

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

 

Если вы используете requestAnimationFrame, все ваши анимации будут гладкими и красивыми, синхронизированными с вашим графическим процессором (GPU) и съедающими гораздо меньше ресурсов центрального процессора (CPU).

 

 

CSS переходы

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

  1. Оптимизации взаимодействия DOM и потребления памяти, чтобы избежать рывков в браузере
  2. Улучшения работы алгоритмов RAF
  3. Использовании аппаратного ускорения (используя мощности GPU для улучшения производительности анимации)

 

А в реальности все это может быть выполнено непосредственно средствами Javascript. GSAP делал это в течение многих лет. Velocity.js – новый анимационный движок, который основательно меняет представление о JavaScript DOM анимации, он использует не только те же методы, но и идет на несколько шагов дальше.

 

Уже можно смело говорить о том, что :

Во-первых, Javascript анимация может соперничать с CSS анимацией.

Во-вторых, Javascript анимация действительно может быть быстрее, чем CSS.

 

Недостатки CSS-библиотек:

  • Переходы исчерпывают ресурсы аппаратного ускорения GPU, что приводит к рывкам и торможению в стрессовых ситуациях. Эти эффекты особенно заметны на мобильных устройствах. (В частности, эти проблемы являются результатом перенагрузки, когда данные передаются между основным потоком браузера и потоком компоновщика. У некоторых css-свойств, таких как transforms и opacity есть иммунитет к перенагрузкам.) Мнение компания Adobe по этому поводу можно прочитать здесь
  • CSS переходы не работают в версиях Internet Explorer ниже 10, в результате чего возникают проблемы доступности для браузеров IE8 и IE9.
  • Т.к. переходы изначально не контролируются Javascript (они просто вызываются из Javascript), то браузер не знает как оптимизировать переходы синхронизируя их с кодом в Javascript, который управляет ими.

 

И наоборот, библиотеки анимации Javascript могут сами решить, когда включить аппаратное ускорение, и они могут работать во всех версиях Internet Explorer, и они идеально подходят для оптимизации анимации.

 

Поэтому следует использовать переходы CSS тогда, когда ведется разработка исключительно для мобильных устройств и анимация состоит только их простых изменений. В таких случаях, переходы – высокопроизводительное и нативное решение, которое позволит сохранить всю анимационную логику внутри файлов стилей и избежать раздутия страницы библиотеками Javascript. Однако, если происходит разработка сложного UI интерфейса, всегда используйте анимационную библиотеку, чтобы анимация оставалась производительной и рабочий процесс был управляем. Подключение уже одной библиотеки дает фантастическое преимущество в работе в управлении css-переходами — Transit.

 

 

JavaScript Анимация

Javascript имеет большие преимущества в производительности. Но, насколько быстр может быть Javascript? Достаточно быстр, чтобы сделать насыщенную 3d-анимацию, которую можно увидеть только с WebGL. И достаточно быстр, чтобы построить мультимедийсный тизер, который можно увидеть , применив Flash или After Effects. И достаточно быстр, чтобы построить виртуальный мир, который, обычно, можно увидеть, применив canvas.

 

Чтобы сравнить производительность популярных библиотек анимации, в т.ч. Transit, который использует CSS-переходы, перейдем к Velocity документации.

 

Остается вопрос: как именно Javascript достиг такого высокого уровня производительности? Ниже приведен краткий список оптимизаций, которые Javascript анимация способна выполнить:

  • Синхронизация DOM со стеком
  • Кеширование значений свойств, чтобы свести к минимуму DOM запросов (это является самой большой проблемой в производительности DOM анимации)
  • Кеширование преобразованных единиц измерений (например, px в %, em и пр.) через взаимосвязанные элементы за один вызов
  • Пропуск обновлений стилей, когда визуально обновления будут не нужны.

 

В Velocity.js используется лучшее методы кеширования конечных значений анимации для повторного использования в качестве следующих стартовых значений для следующей анимации – таким образом избегая перевызова DOM:

$element
	/* Slide the element down into view. */
	.velocity({ opacity: 1, top: "50%" })
	/* After a delay of 1000ms, slide the element out of view. */
	.velocity({ opacity: 0, top: "-50%" }, { delay: 1000 });

 

В этом примере, Velocity уже знает, что второй вызов должен запуститься со стартовым значением прозрачности opacity: 1 и значеним top – 50%.

 

И наконец, давайте сравним две библиотеки – Velocity. Js и GSAP

  • GSAP – быстрый, с большими возможностями анимационной платформы. Velocity представляет из себя простой инструмент для кардинального улучшения производительности UI анимации и рабочего процесса
  • GSAP – коммерческая библиотека, стоит определенных денег. Velocity – библиотека с открытым исходным кодом по лицензии MIT.
  • C точки зрения производительности, Velocity. Js и GSAP неразличимы в реальных проектах.

 

Таким образом, GSAP следует использовать тогда, когда нужен точный контроль над временем выполнения (н-р, remapping, pause/resume/seek), движение (н-р, кривые Безье) или сложная группировка. Эти особенности имеют решающее значение при разработке игр и некоторых нишевых приложений, но они менее распространены в веб-приложениях, при разработке сайтов.

 

 

Velocity.js

То что было много времени уделено GSAP не означает, что о особенностях Velocity не будет рассказано. Наоборот. В 7kb сжатого кода, Velocity не только повторяет всю фунциональность $.animate() в jQuery, но также дополняет его по части анимации, трансформации, вращения, плавности, и прокрутки.

 

Velocity является лучше, чем jQuery, jQuery UI, и CSS переходы вместе взятые.

Использует метод jQuery — $.queue(), и таким образом взаимодействует легко с $.animate(), $.fade() и $.delay функциями jQuery. Также синтаксис Velocity является похожим на $.animate() и не один элемент кода на странице не нуждается в изменении.

 

Рассмотрим Velocity.js на примере

$element
	.delay(1000)
	/* Use Velocity to animate the element's top property over a duration of 2000ms. */
	.velocity({ top: "50%" }, 2000)
	/* Use a standard jQuery method to fade the element out once Velocity is done animating top. */
	.fadeOut(1000);

 

 

В Velocity сложные сцены прокрутки с 3D-анимацией могут быть созданы двумя простыми строками кода:

$element
	/* Scroll the browser to the top of this element over a duration of 1000ms. */
	.velocity("scroll", 1000)
	/* Then rotate the element around its Y axis by 360 degrees. */
	.velocity({ rotateY: "360deg" }, 1000);

 

 

Целью Velocity является оставаться лидером в производительности анимации и удобства.

 

Продолжение следует

comments powered by HyperComments
Понравился материал - нажмите, пожалуйста, на кнопку
=)
Алексей Седляров
2015-01-11 14:01:00
еще одна очень быстрая библиотека TremulaJS https://github.com/garris/TremulaJS