Новая статья совсем не для начинающих. Будем разрабатывать плагины для расширения анимации, а это уже другой уровень…
Материалы данной статьи включены в учебник «jQuery для начинающих». Учебник распространяется бесплатно, и сопровождается интерактивными примерами.
Обучаем animate
Большинство разработчиков уже сталкивалось с функцией animate в jQuery, это достаточно удобный инструмент для анимирования элементов на странице, а я расскажу как вы можете легко изменить поведение данной функции под свои цели.
Для начала затравка – метод animate манипулирует объектом $.fx, в себе он содержит следующие методы:
- cur – возвращает текущее значение атрибута
- custom – отвечает за запуск анимации
- hide/show – простые функции hide/show
- step – каждый отдельный шаг анимации, т.е. вызывается много-много раз
- update – данная функция отвечает за применение атрибутов
Из всего приведенного мы будем расширять объект $.fx.step. Возьмем достаточно тривиальную задачу – заставим плавно изменить цвет шрифта для заданного набора элементов:
$('p').animate({color:'#ff0000'});
Приведенный выше код не даст никакого эффекта, нам потребуется прокачать $.fx.step:
(function($) { // color - свойство с которым мы будем работать $.fx.step.color = function(fx) { // настройки анимации fx.options; // свойство которое изменяем fx.prop; // начальные значения fx.start; // результирующие значения fx.end; // коэффициент, изменяется от 0 до 1 fx.pos; // еденицы измерения fx.unit; }; })(jQuery);
Перед вами основные свойства объекта $.fx – это и есть наши кирпичики, с их помощью будем строить нашу анимацию. Перед работой стоит заглянуть внутрь каждого из приведенных свойств:
// добавим логирование внутрь нашего плагина console.log(fx.options, fx.prop, fx.start, fx.end, fx.pos, fx.unit); /* вывод в консоли: Object duration=5000 old=false curAnim=Object orig=Object / color / 0 / #ff0000 / 0 / px Object duration=5000 old=false curAnim=Object orig=Object / color / 0 / #ff0000 / 0.0008351307317917 / px Object duration=5000 old=false curAnim=Object orig=Object / color / 0 / #ff0000 / 0.0009670080649619717 / px Object duration=5000 old=false curAnim=Object orig=Object / color / 0 / #ff0000 / 0.0010877292712792586 / px Object duration=5000 old=false curAnim=Object orig=Object / color / 0 / #ff0000 / 0.0012155411253085835 / px .. */
Как и предполагалось – метод вызывается N кол-во раз, в зависимости от продолжительности анимации, при этом fx.pos постепенно наращивает своё значение с 0 до 1 (аналогично ведет себя и параметр fx.state, только знаков после запятой у него поменьше, есть ли еще какая разница – я не знаю).
fx.pos, по умолчанию, наращивается линейно, если надо как-то иначе — то стоит посмотреть на easing плагин или дочитать статью до конца (об этом я уже упоминал в статье Эффекты)
Теперь не мешало бы заставить эту систему работать, начнем с инициализации крайних значений (листинг функции parseColor вы сможете найти в самом примере):
// инициализация должна проходить лишь однажды if (fx.state == 0 ) { // получаем текущее значение элемента var start = $.curCSS(fx.elem,'color'); // разбираем на составляющие текущее состояние элемента // start содержит строку вида rgb(255, 255, 255) var res = start.match(/rgb\(([0-9]{1,3}),\s?([0-9]{1,3}),\s?([0-9]{1,3})\)/); if (!res) { // или #ffffff; var res = start.match(/^#(\w{2})(\w{2})(\w{2})$/); var rgb = [parseInt(res[1], 16), parseInt(res[2], 16), parseInt(res[3], 16)]; } else { var rgb = [parseInt(res[1]), parseInt(res[2]), parseInt(res[3])]; } // составляющие запихиваем в fx.start fx.start = rgb; // разбираем что нам нужно получить, и закидываем в fx.end fx.end = parseColor(fx.end); }
Теперь необходимо изменить текущее значение свойств и применить его:
// нехитрое вычисление var R = Math.round(((fx.end[0] - fx.start[0]) * fx.pos) + fx.start[0]); var G = Math.round(((fx.end[1] - fx.start[1]) * fx.pos) + fx.start[1]); var B = Math.round(((fx.end[2] - fx.start[2]) * fx.pos) + fx.start[2]); // непосредственно измение свойств элемента fx.elem.style.color = 'rgb('+R+','+G+','+B+')';
Всё вместе:
$.fx.step.color = function(fx) { // инициализация должна проходить лишь однажды if (fx.state == 0 ) { // получаем текущее значение элемента var start = $.curCSS(fx.elem,'color'); // разбираем на составляющие текущее состояние элемента // start содержит строку rgb(255, 255, 255) var res = start.match(/rgb\(([0-9]{1,3}),\s?([0-9]{1,3}),\s?([0-9]{1,3})\)/); // составляющие запихиваем в fx.start fx.start = [parseInt(res[1]), parseInt(res[2]), parseInt(res[3])]; // разбираем что нам нужно получить, и закидываем в fx.end fx.end = parseColor(fx.end); } // нехитрое вычисление var R = Math.round(((fx.end[0] - fx.start[0]) * fx.pos) + fx.start[0]); var G = Math.round(((fx.end[1] - fx.start[1]) * fx.pos) + fx.start[1]); var B = Math.round(((fx.end[2] - fx.start[2]) * fx.pos) + fx.start[2]); // непосредственно измение свойств элемента fx.elem.style.color = 'rgb('+R+','+G+','+B+')'; };
Результатом станет плавное перетекание исходного цвета к красному (#F00 == #FF0000 == 255,0,0)
Своя анимация
Теперь, познав основы, можем попробовать анимировать некоторый неизвестный параметр shiver (да пусть дрожат пред нами):
$('p').animate({shiver:100});
Идем по натоптанному пути:
(function($) { var left; $.fx.step.shiver = function(fx) { // инициализация должна проходить лишь однажды if (fx.state == 0 ) { // начальное расположение элемента от левого края // дрожать будем по горизонтали left = $.curCSS(fx.elem,'left'); // устанавливаем относительное расположение элемента fx.elem.style.position = 'relative'; } }; })(jQuery);
Так же реализуем саму дрожь элемента:
// если это последняя итерация - вернем всё на своё место if (fx.now == fx.end) { fx.elem.style.left = left; } else if (Math.round(1000 * fx.pos)%2==0) { // четная итерация // непосредственно измение свойств элемента fx.elem.style.left = - Math.round(Math.random()*fx.end) + fx.unit; } else { // нечетная итерация // непосредственно измение свойств элемента fx.elem.style.left = + Math.round(Math.random()*fx.end) + fx.unit; }
Собираем вместе, и смотрим на результат работы…
Пишем свой easing плагин
Возвращаясь к easing’у – мы можем легко написать свою функцию, которой будет следовать анимация. Дабы особо не фантазировать – я взял пример из статьи o MooTools – очень наглядный пример с сердцебиением, которое описывается следующими функциями:
Теперь напишем соответствующий код:
$.extend($.easing, { /** * Heart Beat * * @param x * @param t current time * @param b begInnIng * @param c change In value * @param d duration * * @link http://habrahabr.ru/blogs/mootools/43379/ */ heart:function(x, t, b, c, d) { if (x < 0.3) return Math.pow(x, 4) * 49.4; if (x < 0.4) return 9 * x - 2.3; if (x < 0.5) return -13 * x + 6.5; if (x < 0.6) return 4 * x - 2; if (x < 0.7) return 0.4; if (x < 0.75) return 4 * x - 2.4; if (x < 0.8) return -4 * x + 3.6; if (x >= 0.8) return 1 - Math.sin(Math.acos(x)); } });
Чуть-чуть расширю пример дополнительными функциями (развернем и скомбинируем):
heartIn:function (x, t, b, c, d) { return $.easing.heartIn(x, t, b, c, d); }, heartOut:function (x, t, b, c, d) { return c - $.easing.heartIn(1 - x, t, b, c, d) + b; }, heartInOut: function (x, t, b, c, d) { if (t < d/2) return $.easing.heartIn(1 - x, t, b, c, d) + b; return $.easing.heartOut(1 - x, t, b, c, d) + b; }
Графически это будет выглядеть так:
Результат лучше не показывать кардиолагам.
Цикл статей
- jQuery для начинающих
- jQuery для начинающих. Часть 2. JavaScript Меню
- jQuery для начинающих. Часть 3. AJAX
- jQuery для начинающих. Часть 4. Селекторы
- jQuery для начинающих. Часть 5. Эффекты
- jQuery для начинающих. Часть 6. События
- jQuery для начинающих. Часть 7. Пишем плагины
- jQuery для начинающих. Часть 8. Расширяем фильтры
- jQuery для начинающих. Часть 9. Пишем плагины анимации
Ну как я понял, математика здесь играет большую роль, чем собственно программирование.
А как же таймер? И ограничение на множественные клики? Сейчас получается, что если 100раз ткнуть в картинку, она не скоро остановится. Да и остановить намеренно ее не получится.
Спасибо за статью, очень хорошо пишите.
Ради шутки можно сердцебиение построить опираясь на какую-нибудь последовательность с http://www.physionet.org/. Будет похоже на настоящее))))
Скажу по секрету: в программировании большую роль играет математика чем знание синтаксиса :)
Скажу по секрету: в программировании большую роль играют навыки программирования, чем математика. Они связаны, но никак не зависимы.
Ну смотря какую какую отрасль рассматривать. Я за 5 лет программинга сайтов кроме 4-х элементарных действий ничего не применял.
Вот если бы это было что-то в движении, 3-д. Пришлось бы подумать.
Антон, добрый день!
Вопрос немного не по теме, но сам я не могу его решить.
Имеется тестовая страничка http://test.web-management.ru/benefits.htm
Подскажите пожалуйста, как можно связать движение ползунка с изменением слайдов внизу и чтобы при этом надпись “Сайт как инструмент бизнеса” постепенно заполнялся зеленым цветом. Я новичок в jQuery и не могу настроить такие эффекты.
да, в web-dev математика играет не такую большую роль, как в других областях. Мои знания мат. и функционального анализа, дифф. ур-ий в частных производных, матфизики и фракталов нигде не пригодятся =D
Уважаемый Антон!
С НОВЫМ ГОДОМ! Позвольте выразить Вам самую искреннюю признательность за те материалы, которые Вы размещаете. Все предельно понятно, отлично структурировано, написано доступным языком и крайне полезно. Даже при учете того, что большая часть уже известна и применялась на практике неоднократно, на многие вопросы появляется совершенно иной взгляд (быть может, несколько иное понимание сути).
Еще раз, огромное Вам спасибо! Успехов в Новом Году! :)
С уважением,
AUROSS (Андрей)
Антон, наша главная страница перестала работать потому, что в новом jquery перестал существовать curAnim. Можете подсказать, где посмотреть пример кода, как переползти на jquery 1.6? Просто советы использовать jquery ui как-то мало помогают.
Антон,спасибо!
Спасибо!