Анимация в MooTools. Основы и не только.
Итак, сегодня мы займемся анимацией. Для начала необходимо понять, как реализованы принципы анимации в MooTools. Анимация в MooTools — это изменение какого-либо свойства какого-либо элемента во времени (переход), например, изменение CSS-свойства left — это движение по горизонтали, а background-color — плавное изменение цвета заливки.
- start — этот метод запускает переход.
- set — изменяет значение анимируемого параметра. Вызывается на каждом шаге перехода. По смыслу это абстрактный метод, если его можно так назвать, т.е. каждая реализация анимационного плагина должна переопределить set по-своему.
- cancel — отменяет текущую анимацию.
- pause — приостанавливает текущую анимацию.
- resume — возобновляет приостановленную анимацию.
- fps — количество кадров в секунду для анимации. Характеризует, если можно так сказать, «плавность» анимации — чем он больше, тем «плавнее».
- unit — единица измерения, например «em», «px», «%». Используется для преобразований CSS-свойств.
- link — опция, характеризующая поведение анимации, когда во время перехода был вызван start. Может принимать следующие значения (пример с разными значениями link):
- 'ignore' — все вызовы start во время анимации игнорируются. Используется по умолчанию.
- 'cancel' — текущая анимация будет остановлена и начата новая с параметрами, пришедшими в start.
- 'chain' — все вызовы start во время анимации будут добавлены в цепь и их анимация начнется сразу после того, как закончится текущая.
- Время, прошедшее со старта перехода до текущего момента делится на duration, таким образом получается число от 0 до 1 характеризующее прогресс анимации. Назовем его progress.
- Это число передается в функцию перехода (будет рассмотрено ниже). Результат вычисления функции перехода назовем delta.
- Значение же анимируемого параметра вычисляется так: param = (to − from) × delta + from, где from — начальное значение параметра, to — конечное значение параметра. Очевидно, что при delta равном 0 мы получаем начальное значение параметра, а при 1 — конечное.
Стоит подчеркнуть, что сам по себе класс Fx является абстрактным, то есть ничего сам не анимирует, он оперирует только общими данными для реализации принципов анимации. Непосредственной анимацией занимаются наследники Fx. В основном для анимации элементов на HTML-страницах используются классы, которые анимируют различные CSS-свойства элементов. Об этих классах мы поговорим, а также рассмотрим случай с созданием своего класса, который реализует анимацию не-CSS-свойств.
Уравнения переходов. Написание собственного уравнения.Согласитесь, не очень красиво бы смотрелась анимация перемещения элемента на странице, если бы он резко стартовал и так же резко останавливался в конце пути. Так происходит, если приращение delta (которое упоминалось выше) на протяжении всего времени остается постоянным. Это называется — линейный переход, его уравнение delta = progress. Если взять последовательно несколько значений progress от 0 до 1 и подставить в уравнение, то получим обычную прямую, которая резко начинается в значении 0 и резко заканчивается в 1.
- Linear — прямая (delta = progress).
- Quad — квадратичная функция (delta = progress 2 ).
- Cubic — кубическая функция (delta = progress 3 ).
- Quart — delta = progress 4 .
- Quint — delta = progress 5 .
- Pow — общая степенная функция delta = progress x (по умолчанию степень равна 6).
- Expo — экспоненциальная функция (delta = 2 (progress − 1) × 8 ).
- Circ — четверть окружности (delta = 1 − sin(acos(progress))).
- Sine — кусок синусоиды (delta = 1 − sin((1 − progress) × π / 2)).
- Back — сначала оттягивает delta в минус, а потом плавно доводит до 1.
- Bounce — прыгающий переход.
- Elastic — эластичный переход (единственная ассоциация — резинка :).
- easeIn — используется по умолчанию и ничего не меняет.
- easeOut — вычисляет значение delta по формуле 1 − transition(1 − progress), таким образом разворачивая кривую перехода.
- easeInOut — до середины перехода вычисляет delta по формуле transtition(2 × progress), а после — по (2 − transition(2 × progress)) / 2, совмещая в одном переходе две кривых: прямую и развернутую.
А вот и та самая прыгающая анимация.
Примерчик, показывающий использование различных уравнений переходов в анимации смотреть тут.
А вдруг среди всего разнообразия встроенных уравнений не окажется нужного? Не проблема, всегда можно написать свое, чем мы сейчас и займемся. В идеале уравнение должно быть таким, чтобы при аргументе, равном нулю возвращало 0, а при единице — 1. В этом случае в начале и в конце анимации не будет скачков анимируемого параметра.
В качестве примера мне захотелось написать уравнение, имитирующее колебания на электрокардиограмме. Конечно можно было бы снять с чьей-нибудь кардиограммы точки и интерполировать их в полином, например (для такого даже прогу на третьем курсе писал :), но это было бы не так точно и ресурсоемко (на больших порядках) при конечном использовании. Поэтому функция получилась сложная. Вся условная область определения (от 0 до 1) разделена на интервалы, на каждом из которых определена своя маленькая функция. В итоге получилось следующее:
Как видно, на первом промежутке определена «квадро-функция» для плавного подъема из нуля, далее набор из прямых с разными наклонами и длинами, и в конце четверть окружности для плавного подъема в единицу. Вот как это выглядит в виде кривых:
Добавим эту функцию в объект Fx.Transitions следующим образом:
Fx.Transitions.extend( ). chain( function () < this .move( true , true ); >). chain( function () < this .move( false , false ); >). chain( function () < this .move( true , false ); >). chain( function () < this .move( false , false ); >); >);
Живой пример тут. А тут уже пример никак к цепочкам не относящийся — просто полет фантазии, но прикольный.
Анимация собственных переменных.- добавить в описание класса Extends: Fx для наследования.
- передать опции в базовый конструктор.
- переопределить метод set для применения значения анимируемого параметра к «физике» параметра, в данном случае повернуть индикатор на значение угла.
- вызвать start для начала анимации.
Метод, который реагировал на клик мыши вместо мгновенного изменения угла теперь вызывает метод start и передает в него текущее значение угла поворота индикатора и значение угла, на который он должен быть повернуть после окончания анимации:
captureMouse: function (e) = this .options.minAngle) && (mouseAngle <= this .options.maxAngle)) // Стартуем анимацию перехода индикатора в место клика. this .start( this .angle, mouseAngle); >
Вот и все, у нас появился анимированный переход, лицезреть который можно здесь.
Стандартные анимационные плагины. Fx.Tween.Этот класс является простейшим классом, анимирующим любое CSS-свойство элемента. Для работы ему нужна ссылка на анимируемый элемент, имя анимируемого CSS-свойства и диапазон значений. Пример создания:
// Здесь мы будем менять CSS-свойство top у элемента с идентификатором 'Ball'. var fx = new Fx.Tween( 'Ball' , < property: 'top' , duration: 900, link: 'cancel' >); var transitionSelect = $( 'Transition' ); var modifierSelect = $( 'Modifier' ); var test = $( 'Test' );
// При возникновении одного из следующих событий запустить анимацию. modifierSelect.addEvent( 'change' , startAnimation); transitionSelect.addEvent( 'change' , startAnimation); test.addEvent( 'click' , startAnimation);
function startAnimation()
В HTML-коде примера два выпадающих списка, анимируемый шарик и кнопка на всякий пожарный.
Fx.Morph.Используется чаще, чем Fx.Tween потому что может одновременно анимировать несколько CSS-свойств элемента. Конструктор почти такой же как и у Fx.Tween за исключением отсутствия опции property, вместо нее в метод start передается объект, описывающий, какие CSS-свойства необходимо анимировать и в каких диапазонах. Например:
означает, что анимироваться будут два CSS-свойства: margin-left (от 0 до 10) и background-color (от '#EEE' до '#555'). Диапазоны значений можно и не указывать, а только указать конечное значение, тогда в качестве начального будет взято текущее значение, указанное в стиле элемента. В качестве примера можно привести использование Fx.Morph для создания анимированного меню:
var menuHeadItems = $$( '#Menu .MenuHeadItem' );
// Для каждого пункта меню стартуем анимацию с прогрессивной задержкой 100i ms. // Анимируется два параметра: opacity и margin-left. Таким образом элемент "выезжает" // слева одновременно с изменением прозрачности до 1. morph.start.delay(i * 100, morph, );
item.addEvents( ); >);
Fx.Slide.Довольно полезный класс, когда нужно чтобы что-то откуда-то выехало или заехало. Конструктор очень похож на все предыдущие, поэтому особо останавливаться на нем не буду. Скажу только, что он понимает еще несколько опций, самая важная их которых — это mode, определяющая направление «выезжания»: вертикальное или горизонтальное. На основе этого класса сделаны еще два примера с анимированными меню: первый и второй. Официальный пример.
Fx.Elements.Позволяет удобно анимировать любое количество CSS-свойств для любого количества элементов одновременно. В его конструктор передается массив элементов, над которыми будут осуществляться преобразования. А вся прелесть заложена в методе start — туда передается массив объектов для преобразования. Получается, каждому элементу из массива, переданного в конструкторе соответствует элемент объект из массива, переданного в start. Таким образом осуществляется массовая анимация элементов.
В примере ниже изменяется прозрачность массива элементов при наведении на них курсора, причем чем ближе элемент к тому, что в данный момент под курсором, тем меньше его прозрачность, а чем дальше — тем больше:
var elements = $$( '#ElementsContainer .Element' ); var elementsFx = new Fx.Elements(elements, < duration: 500, link: 'cancel' >);
elements.each( function (element, i) ); >);
Надеюсь, что читателям было интересно закопаться поглубже в реализацию анимации в MooTools. Большинство из описанного здесь должно быть применимо и к другим фреймворкам. Спасибо за внимание.