Слава Богу, у нас есть спецификация!

В этой статье описаны основные особенности и приведено множество полезных примеров работы с CSS3 анимацией. Если вы решили использовать данный эффект у себя в проекте, то стоит ознакомиться с представленной информацией. Пожалуйста, обратите внимание, что я не предлагаю никаких альтернативных вариантов и не даю советов о том, как обойтись без обсуждаемых эффектов. Алекс МакКоу когда-то написал очень проницательную и информативную статья под названием “Все, что нужно знать о CSS анимации“.

Поскольку Алекс написал о достоинствах конкретного эффекта, я собираюсь поговорить о технической составляющей, особенно JavaScript оформления. Ниже представлено содержание этой статьи.  Если вы хотите перейти к конкретному разделу, просто выберите один из пунктов оглавления:

01. Точное определение для анимации 02. Когда анимация завершена 03. Свойства анимации 04. Приоритет свойств анимации 05. Переход от и до auto 06. Неявная анимация 07. Анимация и псевдо-элементы 08. Фон вкладок 09. “Невидимые” элементы 10. Анимация перед DOM  11. Отображение индивидуальных особенностей 12. Рекомендации для спецификации 13. Используй команду delay, Люк! 14. Вывод.

Нет ничего нового в разделении задач  — в течение многих лет, мы использовали шаблон двигателей для достижения именно этой цели, отделяя HTML от языка сценариев. Сайт имеет три основные проблемы: структура (HTML), расположение элементов и стиль (CSS) и поведения (JavaScript). CSS уже довольно давно стала влиять на поведенческие особенности сайта, но это совсем другое обсуждение.

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

Перед началом работы с анимацией, стоит упомянуть о маленькой, часто используемой функции помощи. Функция  getComputedStyle() - это средство JavaScript, которое возвращает значение свойств CSS в том виде, в котором их интерпретирует. Этот программный интерфейс приложения (API) возвращается в “DOM уровень 2: getComputedStyle () ” и “ CSS уровень 2: обработанные значения” — которые в основном указывают на то, что обработка стиля является абсолютным значением.

Это нормально для свойств, таких как font-size (размер шрифта), которые принимают только одно значение аргумента и надежно преобразованы в пиксельное значение. Тем не менее, это не распространяется на то, как браузеры должны обрабатывать условное обозначение некоторых свойств, таких как margin (граница) — некоторые браузеры ничего не возвращают, другие всего лишь что-то полу полезное. Тогда нужно рассмотреть свойства с разными, но эквивалентными значениями, такие как, например font-weight’s  bold (жирность шрифта ) и 700. WebKit содержит ошибку, которая извлекает вычисленное значение свойств из псевдо-элементов.

Описанные здесь особенности были выявлены в январе 2013 года благодаря использованию Firefox 18 (Gecko), Opera 12.12 (Presto), Internet Explorer 10 (Trident), Safari 6.0.2 (WebKit), Chrome 23 (WebKit), а также ночных каналов Gecko и WebKit.

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

“Не обладая необходимой информацией, трудно понять ту или иную вещь. Легче ее просто принять”.

– доктор Аксель Раусмайер.

… Но условные допущения часто ошибочны. Используемую в этой статье информацию я получил создавая блок тестирования CSS3 анимации.

1.Определение анимации.

Условное обозначение transition свойства. Спецификация CSS3 анимации определяет следующие четыре свойства CSS для указания изменения состояния аминирования :

  • transition-property (анимация-свойство);
  • transition-duration (анимация-длительность);
  • transition-delay (анимация-задержка);
  • transition-timing-function (анимация-синхронизация-функция).

Свойства CSS в анимации.

transition-property определяет свойство (или свойства) анимации. Установленная по умолчанию команда all означает, что все свойства браузера, имеющие возможность перехода, могут быть изменены для анимации (если transition-duration больше чем 0s). Данное свойство может принимать одно значение или целый список значений, разделенных запятыми (как и все другие transition-* свойства).

Спецификация указывает на то, что браузер должен принимать и сохранять любые свойства, которые он поддерживает. В следующем примере по-прежнему будет работать переход на padding продолжительностью 2 секунды:

transition-property: foobar, padding; 
transition-duration: 1s, 2s; 

В отличие от спецификации, WebKit анализирует команду до transition-property: all. Firefox и Opera анализирует до transition-property: all, padding.

Продолжительность анимации.

Свойство transition-duration  определяет количество времени требуемого для осуществления перехода. Другими словами, это время за которое объект переходит из начального состояния к целевому состоянию. Значение <time> устанавливается в секундах или миллисекундах (например, 2.3s и 2300ms устанавливает значение в 2,3 секунды).

Хотя спецификация подразумевает, что значение должно быть положительным числом,  Opera также принимает значение -5s 39 — по крайней мере в течение выполнения getComputedStyle(). Для Opera и Internet Explorer (IE) нельзя установить значение меньшее чем 10ms, хотя для спецификации нет такого ограничения. Данное ограничение довольно логично, ведь вполне очевидно, что вы бы не смогли заметить анимацию продолжительностью 9 миллисекунд. WebKit (за исключением текущего ночного WebKit) содержит ошибку в реализации команды getComputedStyle(), которая возвращает значение 0.009999999776482582s вместо 0.01s. По крайней мере, второй вариант представления является общепринятым значением для всех браузеров.

Задержка анимации.

Свойство transition-delay определяет время ожидания перед выполнением перехода, также используя значение <time>. Переменная delay может принимать отрицательные значения, которые приводят к мгновенному переходу и создают впечатление, как будто переход начался с компенсацией во времени — по сути, начался с прыжка.

Как и в случае с transition-duration IE и Opera не принимают значений в промежутке -10ms и 10ms. В WebKit возможно также задавать значения с плавающей точкой.

Синхронизация функций.

Свойство transition-timing-function определяет математическую функцию, используемую для расчета значения во время t. Существуют три основных типа: cubic-bezier(x1, y1, x2, y2), step(<number>, start|end) и ключевые слова, которые сопоставляются с предопределенными кубическими кривыми Безье. Скорее всего, вы уже знаете эти ключевые слова linear, ease, ease-in, ease-out и ease-in-out. Математические вычисления кубических кривых Безье можно значительно упростить благодаря использованию компактного Редактора кубических кривых Безье, разработанного Леа Веру. В то время как кубические кривые Безье делают плавные переходы, для них нет step()функций пошаговости. Они вместо этого переходят к следующему значению (т.е. следующий шаг) через регулярные промежутки времени. Это позволяет получить эффект покадровой анимации; для примера ознакомитесь со статьей “Чистая CSS3 типизация анимации с помощью функции step()“.

Вычисленное значение linear, как правило, представлено в виде cubic-bezier(0, 0, 1, 1) — за исключением WebKit, в котором на самом деле возвращается linear. Но не стоит волноваться: в Webkit по прежнему будет возвращать cubic-bezier(0.25, 0.1, 0.25, 1) вместо ease. Нынешний ночной WebKit возвращает ключевое слово для всех идентифицированных ключевых слов.

Спецификация предполагает, что x значение должно быть в пределах от 0 до 1, а значение y  может и не входить в этот диапазон. В отличие от спецификации, WebKit позволяет значениям x выходить за пределы установленного диапазона, по крайней мере вычислительного. На момент написания статьи, браузер Android (версия 4.0) предполагал смешивание диапазонов для x и y, по сути запретив эффекты “отскока”.

2.Когда анимация завершена.

Я уже упоминал, что CSS переходы выполняются асинхронно. Спецификация обеспечивает выполнение события TransitionEnd, чтобы позволить JavaScript синхронизироваться с концом перехода. К сожалению, спецификация довольно своеобразно влияет на событие. Фактически, она просто указывает какое событие должно отвечать за определенное свойство, которое подвергается переходу. Если вам нужно одно слово, чтобы описать ситуацию, то “кошмар” будет подходящим.

Если спецификация устанавливает условные обозначения свойств (например, padding), то переходы должны работать для всех этих свойств, которые она охватывает (padding-top, padding-right и т.д.). Спецификация не может установить, какое событие должно быть названо в событии TransitionEnd. В то время как Gecko, Trident и Presto согласны на использование обычных обозначений для события переходов под-свойств (например, padding-top), даже если переход был определен для условных обозначений свойств (например, padding), WebKit бы воспользоваться возможностью настройки. WebKit вызовет событие для padding, если (и только если) вы указали transition-property: padding, а transition-property: all вызовет событие для padding-left. По некоторым причинам браузер Safari для iPhone 6.0.1 также может вызвать события для font-size и line-height, когда padding завершит переход. Все очень запутанно, не правда ли?

.example {
  padding: 1px;
  transition-property: padding;
  transition-duration: 1s;
}
.example:hover {
  padding: 10px;}

Представленный выше код CSS вызовет различные TransitionEnd события во всех браузерах:

Gecko, Trident, Presto
padding-top, padding-right, padding-bottom, padding-left
WebKit
padding
.example {
  padding: 1px;
  transition-property: all, padding;
  transition-duration: 1s;
}
.example:hover {
  padding: 10px;}

Представленный выше код CSS вызывает различные TransitionEnd события во всех браузерах:

Gecko, Trident, Presto, WebKit
padding-top, padding-right, padding-bottom, padding-left
Safari 6.0.1 на iPhone (не Ipad, заметьте!)
padding-top, padding-right, padding-bottom, padding-left, font-size, line-height

Ранее я уже говорил, что вы можете задавать отрицательное значение для переменной transition-delay, чтобы вызвать “прыжок” в начале перехода. Но что же происходит в течение transition-duration: 1s; transition-delay: -1s;? Gecko и WebKit сразу же перейдут к целевому значению и вызовут событие. А Trident и Presto и вовсе не вызовут никакого события.

В WebKite существует возможность задания переменной значения с плавающей точкой. Это возможно в функции getComputedStyle(), а также в TransitionEnd.elapsedTime — последовательно во всех браузерах. Функция Math.round(event.elapsedTime * 1000) / 1000 будет “устанавливать” для вас это значение.

WebKit и IE реализовали неопределенное расширение до background-position , которое позволяет вызвать TransitionEnd событие для background-position-x и background-position-y вместо background-position.

Таким образом, даже если вы знаете, что переход имел место, вы не сможете рассчитывать на данные от TransitionEnd.propertyName. Если вы сразу не создадите необходимые загрузки JavaScript для нормализации поведения сайта, у вас не будет возможности сделать это в будущем, пока вы не выясните характеристики каждого события. Вполне возможно наличие свойств, о существовании которых вы даже не догадываетесь.

3.Свойства анимации.

Спецификация включает ряд свойств CSS, которые должен поддерживать браузер для осуществления анимированного перехода. Этот список содержит свойство CSS 2.1. Любое из новых свойств будет помечено как способное к анимированию в соответствующих спецификациях — как показывает order Гибкой модели блока.

Значение типа свойств является важным фактором. Свойство margin-top принимает значение <percentage>, но в соответствии с перечнем свойств CSS, только <length> может быть анимировано. Но это не помешало производителями браузеров совершать попытки осуществления переходов для значения <percentage>. Отдельно стоит поговорить о свойстве word-spacing. Спецификация включает в себя значение <percentage>, но на момент написания статьи, ни один из браузеров не в состоянии был создать для него анимацию.

Игнорируя (считаться ненадежными) событие TransitionEnd, свойство переходит от значения А к значению B, если величина функции getComputedStyle()отличается от значений А и В в переходной момент времени. Поскольку нет такого понятия, как “изменение значения CSS свойств” для события, вы будете продолжать работать с выбранным DOM. Использование команды setTimeout()для быстрых переходов (продолжительность меньше, чем несколько сотен миллисекунд) будет ошибочным решением. Лучше всего воспользоваться командой requestAnimationFrame(). Браузер выведет предупредительное сообщение, прежде чем начнется перерисовка изображения на экране, что позволяет захватить пару промежуточных значений во время переходов. Кроме Opera, двигатели всех браузеров уже имеют эту функцию.

Вместо раздувания этой статьи с приведением полной таблицы совместимостей, я послал результаты своей работы Оли Стадхольму (@ boblet), который обновил свой список “Свойств CSS, пригодных для анимирования“.

4.Приоритет свойств анимации.

Спецификации на свойство transition-property гласит, что свойство можно инициализировать несколько раз:

“ Если свойство определено несколько раз в значении ‘анимация-свойство’ (либо само по себе, через условное обозначение, которое его содержит, или через ‘все’ значения), то начавшийся переход будет иметь значение продолжительности, задержки и синхронизации, соответствующее последнему пункту в значении ‘анимация-свойство’, которое определяет возможность анимации”.

Таким образом, мы можем сделать padding переход в течение 1 секунды, пока работает 2 секундный padding-left переход; или определить стиль перехода по умолчанию используя transition-property: all и переписать его для определенных свойств.

В Firefox и IE все это отлично работает. Opera же смешивает порядок приоритетов. Вместо простого использования последнего применяемого свойства из списка, происходит обращение к padding-left более специфическому, чем padding и all.

Реальная проблема — это WebKit. Проблема заключается в возможности управления многоразовыми переходами, если свойство задано несколь …

Если вы хотите прочитать полностью статью, посетите сайт наших спонсоров

Comments are closed.