Функция замедления обычно представляет собой функцию, которая описывает значение свойства с учетом процента полноты. В разных фреймворках используются несколько разные вариации, но концепцию легко понять, как только вы ее поймете, но, вероятно, лучше посмотреть несколько примеров.
Сначала давайте посмотрим на интерфейс, который будут выполнять все наши функции замедления.
Наши функции замедления будут принимать несколько аргументов:
- процентовПолный: (* 1008 * до
1.0
).
- elaspedTime: количество миллисекунд, в течение которых запускалась анимация
- startValue: значение, с которого нужно начинать (или значение, когда процент выполнения равен 0%)
- endValue: значение, которое заканчивается в (или значение, когда процент выполнения равен 100%)
- totalDuration: общая требуемая длина анимации в миллисекундах
И вернет число, представляющее значение, которое должно быть установлено для свойства.
Примечание: это та же сигнатура, которую jQuery использует для своих функций замедления, которые я буду заимствовать для примеров.
Самым простым для понимания является линейное облегчение:
var linear = function(percent,elapsed,start,end,total) {
return start+(end-start)*percent;
}
А теперь, чтобы использовать это:
Допустим, у нас была анимация, которая собиралась работать в течение 1000 миллисекунд и должна была начинаться с 0 и заканчиваться на 50. Передача этих значений в нашу функцию замедления должна сказать нам, какое должно быть действительное значение:
linear(0, 0, 0,50, 1000) // 0
linear(0.25, 250, 0, 50, 1000) // 12.5
linear(0.5, 500, 0, 50, 1000) // 25
linear(0.75, 750, 0, 50, 1000) // 37.5
linear(1.0, 1000, 0, 50, 1000) // 50
Это довольно прямолинейная (не каламбур) анимация. Это простая линейная интерполяция. Если бы вы рассчитывали значение в зависимости от времени, это была бы прямая линия:
![Linear ease](https://i.stack.imgur.com/5tbz1.png)
Давайте взглянем на немного более сложную функцию замедления, квадратичная простота в:
var easeInQuad = function (x, t, b, c, d) {
return c*(t/=d)*t + b;
}
И давайте посмотрим на те же результаты, используя те же входные данные, что и раньше:
easeInQuad(0, 0, 0, 50, 1000) // 0
easeInQuad(0.25, 250, 0, 50, 1000) // 3.125
easeInQuad(0.5, 500, 0, 50, 1000) // 12.5
easeInQuad(0.75, 750, 0, 50, 1000) // 28.125
easeInQuad(1, 1000, 0, 50, 1000) // 50
Обратите внимание, что значения сильно отличаются от нашей линейной легкости. Он начинается очень медленно, затем ускоряется до конечной точки. При завершении анимации на 50% она достигла значения 12,5, что составляет четверть фактического расстояния между указанными нами значениями start
и end
.
Если бы мы построили график этой функции, она бы выглядела примерно так:
![Quad-Ease-In](https://i.stack.imgur.com/gBaaf.png)
Теперь давайте взглянем на простое упрощение:
var easeOutQuad = function (x, t, b, c, d) {
return -c *(t/=d)*(t-2) + b;
};
Это, по сути, делает "противоположную" кривую ускорения замедления. Она начинается быстро, а затем замедляется до своего конечного значения:
![Ease out](https://i.stack.imgur.com/PCaTk.png)
А затем есть функции, которые облегчают как вход, так и выход:
var easeInOutQuad = function (x, t, b, c, d) {
if ((t/=d/2) < 1) return c/2*t*t + b;
return -c/2 * ((--t)*(t-2) - 1) + b;
};
![EaseInOut](https://i.stack.imgur.com/0gXYu.png)
Эта функция запускается медленно и заканчивается медленно, достигая максимальной скорости в середине.
Существует несколько групп замедления / интерполяции, которые вы можете использовать: линейное, квадратичное, кубическое, квартовое, квинтовое, синусоидальное. И есть специальные функции замедления, такие как Bounce иastic, которые имеют свои собственные.
Например, упругая легкость в:
var easeInElastic = function (x, t, b, c, d) {
var s=1.70158;var p=0;var a=c;
if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
if (a < Math.abs(c)) { a=c; var s=p/4; }
else var s = p/(2*Math.PI) * Math.asin (c/a);
return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
},
![Elastic ease in](https://i.stack.imgur.com/jT5j1.png)
Возможно, кто-то еще может объяснить фактическую математическую часть, стоящую за интерполяцией, потому что, честно говоря, я не математик. Но это основной принцип самих функций замедления.
Когда вы запускаете анимацию / анимацию, движок анимации запоминает начальные и конечные значения, которые вы хотите. Затем каждый раз, когда он обновляет, его цифры из того, сколько времени прошло. Он вызывает поставляемую функцию замедления со значениями, чтобы определить значение, которое должно быть установлено для свойства. Пока все функции замедления реализуют одну и ту же сигнатуру, их можно легко заменить, и ядро анимации не должно знать различий. (Что делает для отличного разделения проблем).
Вы заметите, что я избегал явно говорить о x
и y
позициях, потому что замедление не имеет ничего общего с позицией как таковой . Функция замедления просто определяет переход между начальным и конечным значениями. Это могут быть x
координаты, или цвет, или прозрачность объекта.
И фактически, теоретически, вы можете применять разные функции замедления для интерполяции для разных свойств.Надеюсь, это поможет пролить некоторый свет на основную идею.
А вот действительно классный пример (который использует немного другую подпись, но тот же принцип), с которым можно поиграть, чтобы получитьИдея о том, как ослабление относится к позиции.
Редактировать
Вот немного jsFiddle Я собрал вместе, чтобы продемонстрировать некоторые из основныхиспользования в JavaScript.Обратите внимание, что для свойства top
используется анимация с использованием bounce, а для свойства left
используется анимация с использованием квадрата.Используйте ползунок для имитации цикла рендеринга.
Поскольку все функции в объекте easing
имеют одинаковую сигнатуру, вы можете поменять любую из них друг на друга.Прямо сейчас большинство этих вещей жестко запрограммированы (такие как начальные и конечные значения, используемые функции анимации и длина анимации), но в реальном примере помощника по анимации вы захотите передатьв следующих свойствах:
- Изменяемое свойство
- Начальное значение (или, если осталось
undefined
, то использовать его текущее значение) - Конечное значение
- Длина анимации должна быть
- Ссылка на функцию анимации, которую вы хотите использовать.
Механизм анимации будет отслеживать эти настройки на протяжении всего времени.анимации и во время каждого цикла обновления он будет использовать аргумент анимации для вычисления нового значения свойства.