[Перевод] Анализ производительности CSS-анимаций
Что выбрать для анимирования элементов веб-страниц? JavaScript или CSS? Этот вопрос однажды вынужден будет задать себе каждый веб-разработчик. А может — и не однажды.
JavaScript-программисты создали множество библиотек для браузерной анимации. И, похоже, все вокруг оказались склонны к тому, чтобы использовать эти библиотеки в виде готового решения для анимации. Но давайте-ка притормозим. Правильно ли это? Следует ли анимировать элементы веб-страниц с помощью JavaScript? Может, можно положиться на стандартные механизмы CSS и добиться тем самым качественной и высокопроизводительной анимации?
Так как вы это читаете, я могу предположить, что вы знакомы с JavaScript-анимацией. Поэтому предлагаю исследовать тему CSS-анимации в разных её проявлениях, а так же — предлагаю поговорить о производительности такой анимации.
Общие сведения
Анимация в CSS основана на некоторых свойствах элементов. Среди них можно отметить следующие:
- Свойство
position
, которое, в частности, может принимать значенияabsolute
иrelative
. - Свойство
transform
. - Свойство
opacity
. - Свойства
left
,right
,top
,bottom
.
Для начала взглянем на пару экспериментальных проектов, в которых для анимирования элементов используются различные CSS-свойства.
Вот проект, в котором анимируется элемент с идентификатором animate
, свойство которого position
установлено в значение absolute
. Изменениям подвергаются свойства элемента top
и left
.
Страница экспериментального проекта
Ниже показан код, который реализует эту анимацию.
#animate {
position: absolute;
top: 100px;
left: 30px;
width: 100px;
height: 100px;
border-radius: 50%;
background: red;
animation: move 3s ease infinite;
}
@keyframes move {
50% {
top: 200px;
left: 130px;
}
}
Вот проект, в котором такая же анимация реализована с помощью CSS-свойства transform
.
Эта анимация представлена следующим кодом:
#animate {
position: absolute;
top: 100px;
left: 30px;
width: 100px;
height: 100px;
border-radius: 50%;
background: red;
animation: move 3s ease infinite;
}
@keyframes move {
50% {
transform: translate(100px, 100px);
}
}
Давайте воспользуемся этими проектами для того чтобы сделать выводы о производительности CSS-анимаций, и о том, какие именно ресурсы системы используются для их реализации.
Если просто посмотреть на страницы проектов — можно решить, что реализовано в них одно и то же, хоть и с использованием различных подходов. Однако если измерить показатели производительности этих проектов с использованием инструментов разработчика Chrome, то окажется, что они отличаются.
Как браузер выводит страницу?
Прежде чем мы углубимся в исследование производительности, нам нужно понять то, как браузер выводит страницу, и то, какие действия он выполняет в том случае, если на странице происходят какие-то изменения.
Вот как выглядит процесс вывода страницы.
Вывод страницы
Рассмотрим события, которые отражены на этом рисунке.
Recalculate Style
— вычисление стилей, которые будут применены к элементам.Layout
— создание макетов элементов и их размещение на странице.Paint
— заполнение пикселей созданных слоёв, то есть — создание растровых изображений для каждого слоя. GPU будет использовать эти изображения для вывода страницы на экран.Composite Layer
— компоновка слоёв и вывод их на экран. То, что получится в результате, и будет готовой страницей.
Событие Composite Layer
— это как раз то время, когда CPU обменивается данными с GPU для создания анимации. Используя CSS-свойства вроде transform
и opacity
, мы можем перенести нагрузку по формированию анимации с CPU на GPU.
Анимация и GPU
GPU — это, по сути, специализированный компьютер, используемый для работы с изображениями. Он может эффективно обрабатывать большие объёмы графической информации.
В результате, когда происходит событие Composite Layer
, создаётся дополнительный слой. Это — механизм, благодаря которому можно избежать повторного рендеринга анимированного элемента и других элементов интерфейса.
Глядя на следующий рисунок, можно подумать о том, что анимированные элементы расположены на одном и том же слое.
Анимированные элементы (оригинал)
Но если взглянуть на слои так, будто они расположены в трёхмерном пространстве, окажется, что при реализации анимации с помощью свойства transform для красного круга создаётся дополнительный слой. Это даёт возможность вывода высокопроизводительной плавной анимации.
Для анимированного объекта создан дополнительный слой (оригинал)
GPU держит дерево рендеринга объектов в памяти, и, не выполняя повторного рендеринга, может поместить соответствующий слой поверх других слоёв. В случае же анимирования объекта с использованием свойств top
и left
, тот же слой, из-за изменения свойств, рендерится снова и снова. Если поинтересоваться особенностями поведения этих CSS-свойств, то окажется, что top и left воздействуют на макет страницы, что приводит к необходимости выполнения повторной отрисовки страницы и повторной компоновки слоёв.
Анимация с использованием свойства translate и с использованием свойств top и left
Этот рисунок позволяет увидеть серьёзное отличие между анимацией, реализованной с помощью свойства translate
и свойств top
и left
.
В случае с анимацией, созданной с помощью top
и left
, круг рендерится в каждой позиции до тех пор, пока не достигнет крайнего положения. После этого он начинает двигаться к исходному положению.
Ниже показана панель Performance
инструментов разработчика Chrome со сведениями о процессе анимации.
Анимация с использованием свойства translate (оригинал)
Анимация с использованием свойств top и left (оригинал)
Если посмотреть подробные сведения об отдельных задачах, представленных в панели Performance
, можно сделать вывод о том, что в рамках этих задач выполняются разные действия. Так, в случае с top/left-анимацией, в рамках задачи выполняется пересчёт стилей, компоновка слоёв, обновление дерева слоёв, создание макета и рендеринг. В случае с translate-анимацией единственная задача, решаемая GPU, заключается в перемещении слоя без вывода чего-либо в DOM.
В результате, за счёт применения мощных возможностей GPU, при использовании translate-анимации освобождается главный поток. Это способствует повышению производительности приложения. Применение top/left-анимации приводит к созданию большой дополнительной нагрузки на главный поток.
Нагрузка на главный поток, создаваемая translate-анимацией (слева) и top/left-анимацией (справа) (оригинал)
Вышеприведённый рисунок наглядно демонстрирует ту нагрузку, которая ложится на главный поток при выполнении top/left-анимации. Это — результат постоянных изменений, которые необходимо обрабатывать для выполнения такой анимации.
Итоги
В результате можно сделать вывод о том, что, применяя CSS-анимации, стоит обращать внимание на то, какие именно ресурсы системы задействуются при их выполнении. По возможности стоит использовать те из них, которые выполняются средствами GPU.
А какие анимации вы используете в своих проектах?