jQuery для начинающих. Часть 5. Эффекты

Продолжаем изучать jQuery. Переходим к эффектам…

Материалы данной статьи включены в учебник «jQuery для начинающих». Учебник распространяется бесплатно, и сопровождается интерактивными примерами.

Хотел было написать огромную статью о эффектах, с примерами той или иной анимации, но получилось скорее заметка, которая поможет вам понять суть эффектов в jQuery

Animate

Запомните – все эффекты анимации в jQuery крутятся вокруг функции animate – данная функция берет один или несколько CSS свойств элемента и изменяет их исходного до конечного за N-ое количество итераций (количество итераций зависит от указанного времени, но не реже одной итерации в 13ms (если я правильно накопал это значение)).

Функция animate понимает следующие параметры:

  • params – описание CSS свойств элемента, до которых будет происходить анимация (т.е. есть у нас div с высотой 100px – говорим animate({height:200}) – и высота плавно изменяется до 200px)
  • duration – скорость анимации – указываем в миллисекундах, или используя ключевые слова “fast” = 200ms, “normal” = 400ms или “slow” = 600ms
  • easing – указываем какую функцию будем использовать для наращивания значений, на выбор “linear” или “swing” (хотите больше см. Easing Plugin)
  • callback – функция, которая будет вызвана после окончания анимации

Альтернативный способ инициализации:

  • params – описание CSS свойств элемента, до которых будет происходить анимация
  • options – объект настроек:
    • duration – см. выше
    • easing – см. выше
    • complete – аналогичен ранее описанному callback-параметру
    • step – еще одна callback функция – отвечает за пошаговое изменение параметров – пример ниже
    • queue – флаг очереди, если выставить в false – то данная анимация будет игнорировать очередь и запустится сразу

Если заглянуть в руководство пользователя – то в разделе эффектов можно найти еще несколько вспомогательных функций:

  • show( ) – отображает выбранные элементы
  • hide( ) – скрывает выбранные элементы
  • toggle( ) – переключатель между show/hide
  • slideDown( speed, callback ) – выдвигает объект(ы) вниз – увеличивает высоту от 0 до 100%
  • slideUp( speed, callback ) – задвигает объект(ы) вверх – уменьшает высоту от 100% до 0
  • slideToggle( speed, callback ) – переключатель между slideDown/slideUp
  • fadeIn( speed, callback ) – отображает выбранные элементы – изменяет прозрачность элементов
  • fadeOut( speed, callback ) – скрывает выбранные элементы – изменяет прозрачность элементов
  • fadeTo( speed, opacity, callback )- изменяет прозрачность элементов до указанного значения

Самые простые методы hide и show обходятся без функции animate, т.к. манипулируют лишь атрибутом display (демо):

// вызов метода 
$('#my').hide();

// аналогичен
$('#my').css({display:"none"});

// но если задать скорость анимации либо callback функцию,
// то будут изменятся значения height и width

Как я и говорил ранее – остальные вспомогательные функции лишь обертки над animate, приведу пример (демо):

// вызов метода 
$('#my').slideUp();

// аналогичен
$('#my').animate({height:0,padding:0}, function(){
	$(this).css({display:"none"});
});

// вызов метода 
$('#my').fadeOut();

// аналогичен
$('#my').animate({opacity:0}, function(){
	$(this).css({display:"none"});
});

В действительности, реализация данных методов чуть более сложная, но сути это не меняет

Стоит так же обратить внимание на способ задания параметров CSS для animate:

// установит прозрачность элемента в ноль, прозрачность изменяется от 0 до 1
$('#my').animate({opacity:0});

// наращиваем высоту элемента на 200px
$('#my').animate({height:'+=200px'});

// уменьшаем ширину элемента на 50px
$('#my').animate({width:'-=50px'});

// наращиваем высоту элемента до 20in
$('#my').animate({height:'20in'});

Step Callback

Не стоит забывать и о step-функции, приведу пример использования (демо):

var customStep = function(now, obj) {
	now; // текущее значение анимированного параметра
	
	obj.elem;  // объект анимации
	obj.prop;  // параметр который анимируется
	obj.start; // начальное значение
	obj.end;   // конечное значение
	
	obj.pos;   // коэффициент, изменяется от 0 до 1
	           // значение now вычисляется как now = (obj.end - obj.start) * obj.pos
	
	obj.options; // опции настроек анимации
	
	// сделаем вывод текста
	$(this).html('Height: '+now+obj.unit);
}
$("p").animate({height: height}, {step:customStep});

Отключение

Иногда требуется отключить всю анимацию (для дебага к примеру) – воспользуйтесь следующей конструкцией:

jQuery.fx.off = true;

В очередь, … ©

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

$('.panel').animate({left:'+=100'})
	  .animate({top:'+=100'}); // данная анимация добавляется в очередь на выполнение

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

$('.panel').animate({left:'+=100'})
	  .animate({top:'+=100'}, {queue:false});  // таким образом мы указываем, что очередь можно игнорировать

Так же есть функции stop – с помощью данной функции мы можем остановить выполнение текущей либо всех анимаций (демо):

$('.panel').stop();            // останавливаем выполнение текущей анимации
$('.panel').stop(true);        // останавливаем выполнение текущей анимации и всех последующих (чистим очередь)
$('.panel').stop(true, true);  // останавливаем выполнение текущей анимации и всех последующих, но применяем результат текущей
$('.panel').stop(false, true); // останавливаем выполнение только текущей анимации, и применяем её результат

Как очистить очередь мы разобрались, теперь можно чуть-чуть копнуть поглубже, и разобраться как можно управлять очередью. Для этой цели в jQuery служат следующие функции:

  • queue( name ) – возвращает очередь – массив функций
  • queue( name, callback ) – добавляет функцию в очередь
  • queue( name, queue ) – заменяет текущую очередь новой
  • dequeue( name ) – берет первую функцию из очереди и выполняет её

По умолчанию все манипуляции производятся с очередью “fx” – т.е. очередь со всей анимацией

Данные функции могут понадобиться для управления анимации (демо):

$(".panel").queue('fx'); // возвращает очередь эффектов анимации
$(".panel").data('fxqueue'); // аналогично предыдущему вызову

$(".panel").queue(function(){ /*...*/ }); // добавляет новую функцию в очередь анимации

$(".panel").queue("fx", []); // данный вызов очищает очередь анимации - мы устанавливает пустой массив в качестве новой очереди

$(".panel").dequeue(); // запускает первый элемент из очереди

Или вот пример реализации очереди отличной от “fx”:

var queue = $(".panel").queue('custom');
queue.push(function(){
	$(".panel").css({background:'#ffdddd'})
		.dequeue('custom');
});
	
$(".panel").queue('custom', queue)
	.dequeue('custom');

Пока я вижу одну недоработку – все анимации используют очередь “fx”, и никак изменить это нельзя, т.е. анимация либо идет вместе со всеми в этой очереди, либо сама по себе запускается сразу, назначить анимации другую очередь нельзя

Easing

Возвращаясь к анимации, думаю стоит обратить внимание на способ “наращивания” значений CSS свойств, происходит это следующим образом:

param = (to − from) × delta + from;

// from — начальное значение параметра
// to — конечное значение параметра
// delta — коэффициент, при 0 мы получаем начальное значение параметра, а при 1 — конечное

По умолчанию, для изменение delta используется линейное уравнение, опционально можно указать ‘swing’, но используя плагин easing, можно разнообразить этот список (демо) :

  • Quad — квадратичная функция (delta = progress2).
  • Cubic — кубическая функция (delta = progress3).
  • Quart — delta = progress4.
  • Quint — delta = progress5.
  • Expo — экспоненциальная функция (delta = 2(progress − 1) × 8)
  • Circ — четверть окружности (delta = 1 − sin(acos(progress)))
  • Sine — кусок синусоиды (delta = 1 − sin((1 − progress) × π / 2))
  • Back — сначала оттягивает delta в минус, а потом плавно доводит до 1
  • Bounce — прыгающий переход
  • Elastic — эластичный переход (резинка)

Данные функции оперируют следующими параметрами (именование параметров из jquery.js):

  • p – коэффициент прохождения анимации, изменяется от 0 до 1
  • n – коэффициент наложенный на время (p*duration)
  • firstNum – начальное значение = 0
  • diff – изменение значения = 1

При подготовке данного раздела использовались материалы из статьи Анимация в MooTools. Основы и не только

Плагины

Есть несколько плагинов, который расширяют функционал animate (возможно вы используете еще какие – то отпишитесь):

  • easing – дополнительные уравнения для easing (позволит разнообразить анимацию)
  • color – позволяет плавно изменять цвет шрифта/фона/границ
  • backgroundPosition – с его помощью можем анимировать фоновое изображение элементов

Вывод

Вывод напрашивается сам собой – большинство плагинов для анимации – это лишь обертки над animate, и следовательно не всегда стоит подключать сторонние плагины для реализации своей цели.

P.S. Для всех моих читателей – RSS канала доступен по адресу http://anton.shevchuk.name/feed/ (единственный верный).

P.P.S. Еще я постоянно зависаю на твиттере, так что следуйте за мной…

Цикл статей

  1. jQuery для начинающих
  2. jQuery для начинающих. Часть 2. JavaScript Меню
  3. jQuery для начинающих. Часть 3. AJAX
  4. jQuery для начинающих. Часть 4. Селекторы
  5. jQuery для начинающих. Часть 5. Эффекты
  6. jQuery для начинающих. Часть 6. События
  7. jQuery для начинающих. Часть 7. Пишем плагины
  8. jQuery для начинающих. Часть 8. Расширяем фильтры
  9. jQuery для начинающих. Часть 9. Пишем плагины анимации

50 thoughts on “jQuery для начинающих. Часть 5. Эффекты”

  1. А чем этот пост отличается от официальной документации ? Ну, кроме русского языка ?

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

  2. Большое спасибо за цикл статей) благодаря им я теперь уверенно использую jquery в своих проектах.

  3. С очередностью анимации все понятно. Но меня интересует другое

       $("#tLeftColumn").animate({opacity:0}, 300)
    				    .html("<div align='center' id='ContentTitle'>"+ titlemsg +"</div>" + data)
    					.animate({opacity:1});
      });

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

    1. Попробуйте сформировать очередь вручную:

       $("#tLeftColumn").animate({opacity:0}, 300)
      		  .queue(function() {
                            $(this).html("<div align='center' id='ContentTitle' >"+ titlemsg +"</div>" + data);
                            $(this).dequeue();
                        }).animate({opacity:1});
      });
      

      Или так как описано в примере реализации очереди отличной от “fx”.

  4. спасибо, как всегда понятно информативно и полезно!
    так держать!

  5. Sorry to bother you on these comments but I didn’t find where to contact you.
    I’m using QR Code for WordPress and that’s a wonderful app. Thks a lot.
    Just have a tiny suggestion : generated barcodes are very big on the blog and mobile phones in Europe don’t have a powerful macro on the camera. Why not a dynamic service like a bit.ly or tinyurl to generate smaller QR Code/URL ? Well, that’s just an idea. Thanks again for this application
    Jack

  6. Спасиб автору. Несколько месяцев уже читаю ваши статьи. :)

    Сейчас вот пишу слайдер, дабы убрать громоздкий баннер на флеше с главной страницы моего сайта.

    http://leeas.ru сайт галереи граффити вконтакте. На сайте около 9 миллионов картинок. Вернее записей. Хочу попробывать опустить php и напрямую брать из файла информацию посредством js. Как полагаете, возможно ли наладить прямое подключение к базе, либо скажем к тестовому файлу?

  7. Помогите исправить ошибку в javascript
    CMS Drupal вставил javascript в header в файлы page.tpl, page-front.tpl, page-node.tpl:

    $(document).ready(function() {
          $('#s1').cycle({
        fx:      'fade',
        speed:    5000,
        timeout:  2000
    });
    }); 
    

    При первой загрузке страницы собщение IE о ошибке и javascript не запускается но если кликнуть на любую ссылку
    то дальше работает нормально, кроме того при переходе по ссылкам скрипт на каждой странице загружатся заново.
    Как зделать так чтобы скрипт в header не перегружался при переходе? Сайт:http://www.viatm.com/bruk.org.ua

  8. Спасибо за статьи!!
    Решил сделать анимированное меню и столкнулся с такой проблемой, которую ранее замечал на многих сайтах: когда по кнопкам быстро-быстро водишь, потом останавливаешься, кнопки продолжают колбаситься. Полагаю нужно копать в сторону функции stop. Но при странно срабатывает эфект прозрачности. Т.е. когда я навожу курсор, подсказка начинает появляться, не дождавшись пока она появится, я отвожу курсор и снова навожу. Прозрачность подсказки доходит до того уровня, до которого она дошла в прошлый раз и выше не становиться. Т.е. если я отвел курсор когда opacyty был 0.5, то и в следующий раз он будет 0.5, хотя в коде указано что он должен быть 1.0
    Вот пример кода:

    $(document).ready(function() {
    
    	$("a").hover(function() {
    		$("#hide").stop().animate({opacity: "show"});
    	}, function() {
    		$("#hide").stop().animate({opacity: "hide"});
    	});
    
    });
    
    #hide { width:50px; height:50px; position:absolute; top:20px; left:100px; background:#0099FF; display:none}
    

    Спасибо за любую подсказку!)

  9. Столкнулся с проблемой.

    	$("body").mousemove(function(e){
    		$("div#block").animate({/* передвигаем вслед за мышкой */});
    	});

    В моем случае dib#block имеет вид красного квадрата. Так вот при передвижении мыши квадрат сильно тормозит. Насколько я понимаю при каждом событии mousemove в стек помещается функция которая двигает до определенной координаты, поскольку передвижение совершается медленнее чем двигается мышка (даже если скорость равна) в стеке в скором времени насчитывается огромное количество функций. Вот хотелось бы поинтересоваться как преодолеть эту проблему?

    1. Надо останавливать анимацию, и да – еще бы лучше селекторы чутка оптимизировать…

      var $block = $("#block");
      $("body").mousemove(function(e){
          $block.stop(true);
          $block.animate({/* передвигаем вслед за мышкой */});
      });
      
      1. а зачем знак бакса?:

        var $block = $("#block"); .... $block.stop(true);

        просто для удобства (от php) или есть ньюансы?

      2. Я таким образом отделяю jQuery обёртки, т.е. var block – что угодно, а var $block – уже jQuery объект

  10. Добрый день!
    Помогите решить проблему.
    В сайте использую библиотеку jQuery.
    Во всех браузерах скрипты работают нормально за исключением IE, который выдаёт ошибку “Исключение брошено и не поймано” и ссылается при этом на jquery.js
    Заранее очень благодарен!!!

  11. Антон, подскажи решение.
    Есть код

    jQuery(document).ready(function(){ 
    	jQuery("#btn-s").click(function(){
    		jQuery("#commentform").slideToggle("slow");
    		jQuery(this).toggleClass("btn-active");
                    return false;
    	});
    });
    

    Суть – кнопка открывает-закрывает форму добавления комментариев. Далее. Отправка и обновление списка комментов (и формы) выполнены с использованием ajax. Соотвественно теряется слушатель события с ‘новой’ кнопки. Как поступать в таком случае? в инете внятного решения не нашел!

  12. Хочу у себя на сайте реализовать посредством jQuery автоматическую вставку блоков в середину материала. Кроме как к вам обратиться не к кому. Сделал следующий код, но он не помогает.

    $(document).ready(function(){
    		$("#text p").eq(2).after("<div>Тест</div>");
    						   }
    

    В чем ошибка? И можно ли сделать чтобы не только 1 тег вставлялся с тупой надписью, а скрипт например рекламы.

  13. Спасибо за ваши статьи.
    Очень правильный метод объяснений – на примерах. Только так мне кажется и надо учить всему, не только программированию.

    После ознакомления со статьями у меня все еще остался вопрос ради которого собственно я их и читал. Вопрос:

    Как создать всплывающее окно на jquery с блокировкой и затемнением остальной части страницы?

    Я знаю что это можно реализовать через различные плагины, но вешать дополнительно несколько десятков килобайт не прикольно. И так сам jquery весит очень много.

    Если сможете ответить, то буду очень благодарен.

  14. Помогите решить вопрос!
    1) на странице внизу картинки (превьюшки), кликая на 1-ю выезжает блок снизу страницы с описанием (вверху кнопка закрывающая этот блок заезжанием обратно), если закрыть первый блок и выбрать скажим 3-ю картинку то выезжает снизу 3-й блок с инфой
    2) в открытом блоке (который выехал снизу) наверху есть 2-я навигация Влево и Вправо нажимая на которую соответственно слева или справа выезжает соседний блок информации

    1-й пукнт реализую впринципе без проблем а вот 2-й както не выходит никак :(
    блоки информации по ширене в 100% и по высоте в 90% (сверху остается кусочек) но при большом контенте в блоке включается скрол. как не пытался заставить блоки листаться влево,вправо не вышло также не могу пока заставить их включатся по очереди (если начали с первой картинки то еще куда нишло а если с 3-й то первые 2 блока теряются)

  15. Подскажи пожалуйста, как можна программно изменять скорость текущей анимации в зависимости от координаты курсора

  16. Очень полезная статья. Так держать.
    Помоги пожалуйста разобраться.При клике на ссылку все остальные сдвигаются в стороны, при клике на следующую все возвращаются на исходную позицию, и кроме выбранного все остальные сдвигаются в сторону.
    Не работает на ie7.Выдает следующую ошибку.
    Ошибка при анализе значения «margin». Потерянное объявление.

        $(this).animate({margin:'0 0 0 90px'},
    		 {duration:200});
     

    Сам код jQuery

     $('li').click(function() {	
          var current = $(this);
          var id = current.attr('id');
              $('li').each(function(){
    		$(this).css('margin-left','0'); 
    		   });
              $('li').each(function() {			 
    		  $(this).animate({margin:'0 0 0 90px'},
    				    {duration:200});
    		}); 
    	    current.animate({margin:'0'},
    			    {duration:100}); 
    	 });
    
  17. Такая беда:
    $(document).ready(function(){
    $(‘#span_comment’).click(function(){
    $(‘#div_message2’).fadeIn();
    $(‘body’).click(function(){
    $(‘#div_message2’).hide(“slow”);
    });
    return false;
    });
    });
    В блоке div_message2 находится textarea проблема в том что при клике на textarea она закрывается, а должна при нажатии в любом месте кроме этого div скажите в чем проблема?

    1. Добавьте обработчик click для textarea который будут предотвращать “всплытие” события

  18. Я прощу прощения. Я к вам за советом.
    Ситуация следующая.
    Необходимо сделать последовательность:
    1. Анимация
    2. Анимация
    3. Действие

    $('#test').queue(function () {
    	$(this).fadeOut(1000);
    	$(this).dequeue();
    });
    $('#test').queue(function () {
    	$(this).fadeIn(1000);
    	$(this).dequeue();
    });
    $('#test')queue(function () {
    	test++;
    	$('#console').append('Ok');
    	$(this).dequeue();
    });
    

    Пример крайне упрощен для простоты понимания. Вместо обычных fadeIn и fadeOut там происходят манипуляции посложнее.
    По логике вывод текста должен произойти после всех анимаций. Но он показывается сразуже после первой анимации. Подскажите пожалуйста, в чем проблема.

    1. Анимация становится в очередь fx, вы можете использовать какую-нить другую (для jQuery 1.7+) либо вызов dequeue засовывать в calback анимации

  19. Спасибо! Очень полезная статься! Так держать! =)

  20. Антон, здравствуйте.

    В icloud.com при вводе неверных данных форма трясётся вправо-влево. Мне очень нравится эта идея. Я пытался самостоятельно её имитировать:

    $('#wrapper').animate({'left':'+=20px'},'100'
    ).animate({'left':'-=20px'},'100').animate({'left'
    :'+=20px'},'100').animate({'left':'-=20px'},'100'
    ).animate({'left':'+=20px'},'100').animate({'left'
    :'-=20px'},'100').animate({'left':'+=0'},'100'
    );

    Но это получается слишком медленно. Оно не выглядит как жест головой “не-а”. Изменение времени 100 на любое другое лишь замедляет эффект.
    Пытался гуглить, как решить проблему, но так и не смог подобрать верный запрос. Помогите, пожалуйста.

    1. Задавайте скорость анимации числом, а не строкой, т.е. пишите “100” без кавычек

  21. Вот эта самодовольная раскрашенная рожа слева смущает и не дает сосредоточиться.

  22. 13 ms (чуть меньше) это тик встроенных в компьютер часов.

  23. Скорость аниммаци в ms? Непонятно. Скорость это величина изменения чего-то ха единицу времени. То есть время в знаменатеде. А время в числителе это скорее интервал, чем скорость.

  24. Спасибо за статьи, регулярно обращаюсь.
    подскажите как решить вопрос с движением экрана вслед за раскрывающимся списком?
    существует скрытый текст, который после клика по ссылке списком раскрывается и уходит за пределы нижней части экрана.
    задача проста, но решить не осиляю. заранее спасибо!

    1. Ну тут два варианта, либо открывать в таком случае меню вверх, либо проскролить элемент вверх, чтобы было видно выпадающие элементы.

  25. Здраствуйте),підкажіть будь ласка як можна в jQuery змінювати висоту блоку керуючи напрямком, тобто щоб висоту можна було б змінювати або тільки вверх або тільки вниз.
    ДякуЮ!!)

  26. Здравствуйте, Антон.
    Хотел поблагодарить за вашу учебник по Jquery. Хотя это более напоминает справочник т.к. слишком уж компактно, но все равно очень помогает в освоении.
    Кроме того у меня возник вопрос по методу .width. Вводная примерно такова:
    Есть блок у которого #x {width=70%; margin 0, auto;} и присваивается он переменной xx=$(“#”). Далее методом у=xx.width измеряется его ширина. И после всех расчетов через x.append(.y) вставляется нужный модуль.
    Проблема в том что метод .width периодический выдает левые значения, особенно с первой загрузки после обновления скрипта, пока файл не попал в кэш хрома. И как понимаю связано это с тем что блок #x пустой на момент замера.
    Я пока не придумал ничего лучше кроме как принимать значение которое совпало с двумя предыдущими запросами. Но есть ощущение что это костыль, а не решение.
    Пуду признателен за совет.
    ps. Возможно в учебнике стоит чуть больше уделить внимание возможным порядкам операций. долго страдал почему у.css не работал перед операцией x.append(y) ведь заранее прописанный css стиль работает с добавляемым .y.
    Еще раз спасибо.

  27. все доступно и понятно, спасибо за помощь материал и работу над ним. Так держать

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.