Статьи

Красивые приложения с переходами CSS3

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

Новая спецификация HTML 5 (честно говоря, я должен сказать «новая спецификация CSS 3 ») представляет отличный инструмент для обработки простых анимаций: переходы .

В соответствии со спецификацией «Модуль переходов CSS уровня 3» на сайте W3C , переходы CSS3 позволяют плавно изменять свойства в значениях CSS в течение указанной продолжительности .

Целью этой статьи будет сначала описать концепцию переходов, а затем посмотреть, как работает CSS3 Transitions и как мы можем работать с браузерами, которые не поддерживают эту функцию:

  1. CSS3 переходы
  2. Собираем все вместе
  3. Переходы без переходов CSS3
  4. Вывод
  5. Идти дальше

Кроме того, я предлагаю вам прочитать « Введение в анимацию CSS3 » (автор David Rousset ), которая является отличным компаньоном для этой статьи.

Чтобы увидеть, как можно использовать переходы CSS3, я разработал пример игры, в которой переходы CSS3 используются для анимации ячеек головоломки (и откат к JavaScript, если ваш браузер не поддерживает переходы CSS3):


Чтобы получить игровую версию этой игры,
зайдите в мой блог здесь . Код этой игры доступен
здесь .

CSS3 переходы

Вступление

Вначале рабочая группа CSS W3C сопротивлялась добавлению переходов в CSS, утверждая, что переходы на самом деле не являются стилевыми свойствами. Но в итоге дизайнерам и разработчикам удалось убедить их, что переходы связаны с динамическими стилями и могут происходить в файле CSS.

Согласно сайту W3C, CSS3 Transitions может анимировать следующие типы свойств: (нажмите здесь, чтобы показать их)

  • цвет : интерполируется с помощью красного, зеленого, синего и альфа-компонентов (каждый рассматривается как число, см. ниже)
  • длина : интерполируется как действительные числа.
  • Процент : интерполируется как действительные числа.
  • целое число : интерполируется через дискретные шаги (целые числа). Интерполяция происходит в реальном числовом пространстве и преобразуется в целое число с помощью floor ().
  • число : интерполируется как действительные (с плавающей запятой) числа.
  • список трансформации : см. спецификацию CSS Transforms: http://www.w3.org/TR/css3-2d-transforms/
  • прямоугольник : интерполируется через компоненты x, y, width и height (обрабатывая каждый как число).
  • видимость : интерполируется через дискретный шаг. Интерполяция происходит в реальном числовом пространстве между 0 и 1, где 1 «видимо», а все остальные значения «скрыты».
  • shadow : интерполируется через компоненты color, x, y и blur (обрабатывая их как цвет и числа, где это уместно). В случае, когда есть списки теней, более короткий список заполняется в конце тенями, цвет которых прозрачен, а все длины (x, y, blur) равны 0.
  • градиент : интерполируется через позиции и цвета каждой остановки. Они должны иметь одинаковый тип (радиальный или линейный) и одинаковое количество остановок для анимации.
  • сервер рисования (SVG): интерполяция поддерживается только между: градиент в градиент и цвет в цвет. Затем они работают, как указано выше.
  • Список разделенных пробелами выше : если списки имеют одинаковое количество элементов, каждый элемент в списке интерполируется с использованием приведенных выше правил. В противном случае, нет интерполяции.
  • свойство сокращения : если все части сокращения могут быть анимированы, тогда интерполяция выполняется так, как если бы каждое свойство было задано индивидуально.

И следующие свойства должны поддерживаться для переходов: (нажмите здесь, чтобы показать их)

  • цвет фона ( цвет )
  • фоновое изображение ( только градиенты )
  • background-position ( процент и длина )
  • цвет рамки нижний ( цвет )
  • граница нижней ширины ( длина )
  • бордюрный цвет ( цвет )
  • Цвет рамки слева ( цвет )
  • border-left-width ( длина )
  • рамка-цвет справа ( цвет )
  • border-right-width ( длина )
  • интервал границы ( длина )
  • пограничный верхний цвет ( цвет )
  • border-top-width ( длина )
  • ширина бордюра ( длина )
  • низ ( длина и процент )
  • цвет ( цвет )
  • обрезать ( прямоугольник )
  • размер шрифта ( длина и процент )
  • Вес шрифта ( число )
  • сеточного * ( различные )
  • высота ( длина и процент )
  • слева ( длина и процент )
  • межбуквенный интервал ( длина )
  • высота строки ( число, длина и процент )
  • нижнее поле ( длина )
  • поле слева ( длина )
  • поле справа ( длина )
  • поле-вершина ( длина )
  • максимальная высота ( длина и процент )
  • максимальная ширина ( длина и процент )
  • минимальная высота ( длина и процент )
  • минимальная ширина ( длина и процент )
  • непрозрачность ( число )
  • цвет контура ( цвет )
  • контурное смещение ( целое число )
  • контурная ширина ( длина )
  • padding-bottom ( длина )
  • отступ слева ( длина )
  • правый отступ ( длина )
  • padding-top ( длина )
  • справа ( длина и процент )
  • текстовый отступ ( длина и процент )
  • текстовая тень ( тень )
  • верх ( длина и процент )
  • выравнивание по вертикали ( ключевые слова, длина и процент )
  • видимость ( видимость )
  • ширина ( длина и процент )
  • интервал между словами ( длина и процент )
  • z-индекс ( целое число )
  • зум ( число )

SVG

Свойства объектов SVG являются анимируемыми, когда они определены как animatable: true в спецификации SVG: http://www.w3.org/TR/SVG/struct.html .

Объявления

Чтобы объявить переход в файле CSS, вам просто нужно написать следующий код:

69.transition-property: all;
70.transition-duration: 0.5s;
71.transition-timing-function: ease;
72.transition-delay: 0s;

Это объявление определяет, что любое обновление любого свойства будет выполнено за 0,5 с (а не сразу).

Вы также можете определить свои переводы для каждого свойства:

73.transition-property: opacity left top;
74.transition-duration: 0.5s 0.8s 0.1s;
75.transition-timing-function: ease linear ease;
76.transition-delay: 0s 0s 1s;

И, наконец, вы можете использовать сокращенное свойство « Переход », чтобы определить все, что вам нужно в одной строке:

77.transition: all 0.5s ease 0s;

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

78.transition: opacity 0.5s ease 0s, left 0.8s linear 0s;

 

Переходы будут срабатывать при обновлении свойства целевого объекта. Обновление можно выполнить с помощью JavaScript или CSS3, назначив новый класс тегу .

Например, используя IE10, если у вас есть следующее объявление CSS3:

79.-ms-transition-property: opacity left top;
80.-ms-transition-duration: 0.5s 0.8s 0.5s;
81.-ms-transition-timing-function: ease linear ease;

Когда вы обновите непрозрачность вашего тега, текущее значение будет анимировано до нового значения в течение 0,5 с с помощью функции замедления по времени (которая обеспечивает плавную анимацию).

Нелинейные переходы

Строка «transition-timer-function» определяет, что переход не будет линейным, но будет использовать функцию хронирования для создания нелинейной анимации.

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

Поддерживаются следующие функции:

  • линейный : постоянная скорость
  • cubic-bezier : Скорость будет рассчитываться в соответствии с кубической кривой Безье, определяемой двумя контрольными точками: P0 и P1 (поэтому вам нужно будет определить 4 значения здесь: P0x, P0y и P1x, P1y.
  • легкость : скорость будет вычислена с помощью кубического Безье (0,25, 0,1, 0,25, 1)
  • непринужденность : скорость будет вычислена с помощью кубического Безье (0,42, 0, 1, 1)
  • easy-inout : скорость будет вычислена с помощью кубического Безье (0,42, 0, 0,58, 1)
  • замедление : скорость будет вычислена с помощью кубического Безье (0, 0, 0,58, 1)

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

<p> Ваш браузер не поддерживает iframes. </ p> Нажмите здесь, чтобы показать демонстрацию: <a href=»http://www.catuhe.com/msdn/transitions/easingfunctions.htm»> http: // www .catuhe.com / MSDN / переходы / easingfunctions.htm </a>

Этот симулятор написан с чистым кодом JavaScript, чтобы облегчить понимание функции:

88.TRANSITIONSHELPER.computeCubicBezierCurveInterpolation = function (t, x1, y1, x2, y2) {
89.// Extract X (which is equal to time here)
90.var f0 = 1 - 3 * x2 + 3 * x1;
91.var f1 = 3 * x2 - 6 * x1;
92.var f2 = 3 * x1;
93. 
94.var refinedT = t;
95.for (var i = 0; i < 5; i++) {
96.var refinedT2 = refinedT * refinedT;
97.var refinedT3 = refinedT2 * refinedT;
98. 
99.var x = f0 * refinedT3 + f1 * refinedT2 + f2 * refinedT;
100.    var slope = 1.0 / (3.0 * f0 * refinedT2 + 2.0 * f1 * refinedT + f2);
101.    refinedT -= (x - t) * slope;
102.    refinedT = Math.min(1, Math.max(0, refinedT));
103.    }
104.     
105.    // Resolve cubic bezier for the given x
106.    return 3 * Math.pow(1 - refinedT, 2) * refinedT * y1 +
107.    3 * (1 - refinedT) * Math.pow(refinedT, 2) * y2 +
108.    Math.pow(refinedT, 3);
109.    };

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

задержка

Строка «transition-delay» определяет задержку между обновлением свойства и началом перехода

События

Событие возникает в конце перехода: « TransitionEnd ». В соответствии с вашим браузером правильное имя будет:

  • Chrome & Safari: webkitTransitionEnd
  • Firefox: mozTransitionEnd
  • Опера: oTransitionEnd
  • Internet Explorer: MSTransitionEnd

Событие предоставит вам следующую информацию:

  • propertyName : имя анимированного свойства
  • elapsedTime : время выполнения перехода в секундах.

Вот пример использования для IE10: 116. block.addEventListener («MSTransitionEnd», onTransitionEvent);

Подробнее о переходах CSS3

В основном я могу предложить две причины, по которым переходы CSS3 действительно полезны:

  • Аппаратное ускорение: переходы CSS3 напрямую обрабатываются на графическом процессоре (если он доступен) и дают более плавные результаты. И это действительно важно на мобильных устройствах, где вычислительная мощность действительно ограничена
  • Лучшее разделение между кодом и дизайном : для меня разработчик не должен знать об анимации или чем-либо, связанном с дизайном. Точно так же дизайнер / художник не должен знать о JavaScript. Вот почему CSS3 Transitions действительно интересны, так как дизайнеры могут описывать все переходы в CSS без необходимости разработчиков

Поддержка и запасной вариант

Начиная с PP3, IE10 (который можно загрузить с Windows 8 Developer Preview здесь ) поддерживает переходы CSS3:

Этот отчет был создан с помощью http://caniuse.com/#search=CSS3 переходов .

Конечно, поскольку спецификация не закончена ( рабочий проект ), вы должны использовать префиксы поставщика, такие как -ms-, -moz-, -webkit-, -o-.

Очевидно, мы видим, что нам необходимо предоставить прозрачное решение для всех типов браузеров. Наилучшим способом будет разработка API, который сможет определять поддержку переходов CSS3. Если браузер не поддерживает эту функцию, мы вернемся к некоторому коду JavaScript.

Важно поддерживать запасной метод, если вы полагаетесь на переходы для функциональности веб-сайтов. Если вы не хотите этого делать, вам следует рассмотреть возможность использования переходов только для улучшения дизайна . В этом случае сайт все еще будет работать, но только поддерживаемые браузеры будут работать в полном объеме. Мы говорим здесь о « прогрессивных улучшениях », поскольку чем мощнее браузер, тем больше возможностей он получает.

Переходы без переходов CSS3

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

Прежде всего, мы создадим объект контейнера для нашего пространства имен:

119.    var TRANSITIONSHELPER = TRANSITIONSHELPER || {};
120.     
121.    TRANSITIONSHELPER.tickIntervalID = 0;
122.     
123.    TRANSITIONSHELPER.easingFunctions = {
124.    linear:0,
125.    ease:1,
126.    easein:2,
127.    easeout:3,
128.    easeinout:4,
129.    custom:5
130.    };
131.     
132.    TRANSITIONSHELPER.currentTransitions = [];

Чтобы поддерживать одинаковый уровень функций замедления, мы должны объявить enum со всеми необходимыми полями.

Инструментарий основан на функции, которая вызывается каждые 17 мс (для достижения анимации при 60 кадрах в секунду). Функция будет перечислять через коллекцию активных переходов. Для каждого перехода код будет оценивать следующее значение с учетом текущего значения и целевого значения.

Нам понадобятся некоторые удобные функции для извлечения значений используемых свойств и единиц:

133.    TRANSITIONSHELPER.extractValue = function (string) {
134.    try {
135.    var result = parseFloat(string);
136.     
137.    if (isNaN(result)) {
138.    return 0;
139.    }
140.     
141.    return result;
142.    } catch (e) {
143.    return 0;
144.    }
145.    };
146.     
147.    TRANSITIONSHELPER.extractUnit = function (string) {
148.     
149.    // if value is empty we assume that it is px
150.    if (string == "") {
151.    return "px";
152.    }
153.     
154.    var value = TRANSITIONSHELPER.extractValue(string);
155.    var unit = string.replace(value, "");
156.     
157.    return unit;
158.    };

Основная функция обработает активные переходы и вызовет функцию кубического Безье для оценки текущих значений:

159.    TRANSITIONSHELPER.tick = function () {
160.    // Processing transitions
161.    for (var index = 0; index < TRANSITIONSHELPER.currentTransitions.length; index++) {
162.    var transition = TRANSITIONSHELPER.currentTransitions[index];
163.     
164.    // compute new value
165.    var currentDate = (new Date).getTime();
166.    var diff = currentDate - transition.startDate;
167.     
168.    var step = diff / transition.duration;
169.    var offset = 1;
170.     
171.    // Timing function
172.    switch (transition.ease) {
173.    case TRANSITIONSHELPER.easingFunctions.linear:
174.    offset = TRANSITIONSHELPER.computeCubicBezierCurveInterpolation(step, 0, 0, 1.0, 1.0);
175.    break;
176.    case TRANSITIONSHELPER.easingFunctions.ease:
177.    offset = TRANSITIONSHELPER.computeCubicBezierCurveInterpolation(step, 0.25, 0.1, 0.25, 1.0);
178.    break;
179.    case TRANSITIONSHELPER.easingFunctions.easein:
180.    offset = TRANSITIONSHELPER.computeCubicBezierCurveInterpolation(step, 0.42, 0, 1.0, 1.0);
181.    break;
182.    case TRANSITIONSHELPER.easingFunctions.easeout:
183.    offset = TRANSITIONSHELPER.computeCubicBezierCurveInterpolation(step, 0, 0, 0.58, 1.0);
184.    break;
185.    case TRANSITIONSHELPER.easingFunctions.easeinout:
186.    offset = TRANSITIONSHELPER.computeCubicBezierCurveInterpolation(step,0.42, 0, 0.58, 1.0);
187.    break;
188.    case TRANSITIONSHELPER.easingFunctions.custom:
189.    offset = TRANSITIONSHELPER.computeCubicBezierCurveInterpolation(step, transition.customEaseP1X, transition.customEaseP1Y, transition.customEaseP2X, transition.customEaseP2Y);
190.    break;
191.    }
192.     
193.    offset *= (transition.finalValue - transition.originalValue);
194.     
195.    var unit = TRANSITIONSHELPER.extractUnit(transition.target.style[transition.property]);
196.    var currentValue = transition.originalValue + offset;
197.     
198.    transition.currentDate = currentDate;
199.     
200.    // Dead transition?
201.    if (currentDate >= transition.startDate + transition.duration) {
202.    currentValue = transition.finalValue; // Clamping
203.    TRANSITIONSHELPER.currentTransitions.splice(index, 1); // Removing transition
204.    index--;
205.     
206.    // Completion event
207.    if (transition.onCompletion) {
208.    transition.onCompletion({propertyName:transition.property,elapsedTime:transition.duration});
209.    }
210.    }
211.     
212.    // Affect it
213.    transition.target.style[transition.property] = currentValue + unit;
214.    }
215.    };

Текущая версия инструментария поддерживает только числовые значения, но если вы хотите анимировать сложные значения (например, цвет), вам просто нужно разложить их на простые значения.

Регистрация перехода в системе будет осуществляться с использованием следующего кода:

 

216.    TRANSITIONSHELPER.transition = function (target, property, newValue, duration, ease, customEaseP1X, customEaseP1Y,
customEaseP2X, customEaseP2Y, onCompletion) {
217.     
218.    // Create a new transition
219.    var transition = {
220.    target: target,
221.    property: property,
222.    finalValue: newValue,
223.    originalValue: TRANSITIONSHELPER.extractValue(target.style[property]),
224.    duration: duration,
225.    startDate: (new Date).getTime(),
226.    currentDate: (new Date).getTime(),
227.    ease:ease,
228.    customEaseP1X:customEaseP1X, 
229.    customEaseP2X:customEaseP2X,
230.    customEaseP1Y: customEaseP1Y,
231.    customEaseP2Y: customEaseP2Y,
232.    onCompletion: onCompletion
233.    };
234.     
235.    // Launching the tick service if required
236.    if (TRANSITIONSHELPER.tickIntervalID == 0) {
237.    TRANSITIONSHELPER.tickIntervalID = setInterval(TRANSITIONSHELPER.tick, 17);
238.    }
239.     
240.    // Remove previous transitions on same property and target
241.    for (var index = 0; index < TRANSITIONSHELPER.currentTransitions.length; index++) {
242.    var temp = TRANSITIONSHELPER.currentTransitions[index];
243.     
244.    if (temp.target === transition.target && temp.property === transition.property) {
245.    TRANSITIONSHELPER.currentTransitions.splice(index, 1);
246.    index--;
247.    }
248.    }
249.     
250.    // Register
251.    if (transition.originalValue != transition.finalValue) {
252.    TRANSITIONSHELPER.currentTransitions.push(transition);
253.    }
254.    }; 

Функция «галочка» запускается при активации первого перехода.

Наконец, вам просто нужно использовать modernizr, чтобы определить, поддерживается ли переходы CSS3 текущим браузером. Если нет, то вы можете Откат к нашему инструментарию.

Код для TransitionsHelper можно скачать здесь: http://www.catuhe.com/msdn/transitions/transitionshelper.js

Например, в моей игре-головоломке для анимации ячеек используется следующий код:

255.    if (!PUZZLE.isTransitionsSupported) {
256.    TRANSITIONSHELPER.transition(block.div, "top", block.x * totalSize + offset, 500, TRANSITIONSHELPER.easingFunctions.ease);
257.    TRANSITIONSHELPER.transition(block.div, "left", block.y * totalSize + offset, 500, TRANSITIONSHELPER.easingFunctions.ease);
258.    }
259.    else {
260.    block.div.style.top = (block.x * totalSize + offset) + "px";
261.    block.div.style.left = (block.y * totalSize + offset) + "px";
262.    }

Мы можем заметить, что я мог бы использовать другой способ для анимации моих ячеек, когда поддерживаются переходы CSS3: я мог бы определить коллекцию классов CSS3 с предопределенными левым и верхним значениями (по одному для каждой ячейки), чтобы воздействовать на них для правых ячеек.

Некоторые платформы и наборы инструментов уже существуют для поддержки программных переходов:

Кстати, вы также можете использовать старый добрый метод animate () jQuery.

Вывод

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

Кстати, есть два решения, если вы хотите реализовать запасной вариант JavaScript:

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

Идти дальше

Лицензия

Эта статья, наряду со всеми связанными исходным кодом и файлами, распространяется под лицензией The Code Project Open License (CPOL).