Анимация
Step-by-step
Хотелось бы отдельно остановиться на функции "step", и для наглядности приведу пример реализации подобной функции, которая отображает текущее значение анимированного параметра:
var customStep = function(now, obj) { obj.elem; // объект анимации obj.prop; // параметр, который анимируется obj.start; // начальное значение obj.end; // конечное значение obj.pos; // коэффициент, изменяется от 0 до 1 obj.options; // опции настроек анимации now; // текущее значение анимированного параметра, вычисляется как // now = (obj.end - obj.start) * obj.pos $(this).html(obj.prop +': '+now+obj.unit); // вывод текста } $("#box").animate({height: "+=10px"}, {step: customStep});
Мне ни разу не приходилось использовать step-функции, лишь только для примера
В очередь…©
Немного об очередности работы функции "animate()" – большинство читателей, наверное, уже знакомо с организацией последовательной анимации – для этого мы можем использовать цепочку вызовов:
$('#box ') // говорим что меняем .animate({left:'+=100'}) // следующий вызов добавляется в очередь на выполнение .animate({top:'+=100'})
Для параллельного запуска анимации, необходимо будет внести следующие изменения:
$('#box') // говорим что меняем .animate({left:'+=100'}) // следующий вызов будет игнорировать очередь .animate({top:'+=100'}, {queue:false})
Есть ещё чудесная функция "stop()", которая позволяет остановить текущую анимацию на полпути, а так же почистить очередь при необходимости. Для обеспечения различного поведения функции, она принимает три параметра:
queue – имя очереди; для работы с очередью анимации "fx" данный параметр опускаем ("fx" – очередь по умолчанию)
clearQueue – флаг очистки очереди
jumpToEnd – применить результат анимации али нет
// останавливаем выполнение текущей анимации $('#box').stop(); // останавливаем выполнение текущей анимации // и всех последующих (чистим очередь) $('#box').stop(true); // останавливаем выполнение текущей анимации и всех последующих // но применяем результат текущей $('#box').stop(true, true); // останавливаем выполнение только текущей анимации // и применяем её результат $('#box').stop(false, true);
Пример есть, и требует ваших проб и ошибок:
<!DOCTYPE html> <html dir="ltr" lang="en-US"> <head> <meta charset="UTF-8"/> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Пример работы очередей анимации</title> <link rel="profile" href="http://gmpg.org/xfn/11"/> <link rel="shortcut icon" href="http://anton.shevchuk.name/favicon.ico"/> <link rel="stylesheet" href="css/styles.css"/> <script type="text/javascript" src="js/jquery.js"></script> <script type="text/javascript" src="js/code.js"></script> <style> article { position: relative; height: 600px; } #box { background: #55f; position: relative; margin: 10px; width: 80px; height: 80px; } #box span { display: inline-block; background: #fff; font-size: 22px; line-height: 22px; text-align: center; width: 16px; margin: 6px 8px; padding: 2px; border: 1px solid #000; border-radius: 2px; } .red { color:red; } </style> </head> <body> <div id="content" class="wrapper box"> <menu label="Try..."> <a href="animate.html" title="go prev" class="button alignleft" rel="prev">← Prev </a> <a href="index.html" title="back to Index" class="button alignleft" rel="index">Index §</a> <a href="#" title="reload" class="button alignleft" onclick="window.location.reload();return false">Reload ¤</a> <a href="animate.game.html" title="go next" class="button alignright" rel="next">Next →</a> <hr/> <pre><code contenteditable="true"><em>// with queue</em> $(<span>'#box'</span>).animate({ <span>'left'</span>:<span>'+=100'</span> }, 2000).animate({ <span>'top'</span>:<span>'+=100'</span> }, 2000)</code></pre> <button type="button" class="code">Run Code</button> <pre><code contenteditable="true"><em>// without queue</em> $(<span>'#box'</span>).animate({ <span>'left'</span>:<span>'-=100'</span> }, 2000).animate({ <span>'top'</span>:<span>'-=100'</span> }, {queue:false, duration:2000})</code></pre> <button type="button" class="code">Run Code</button> <pre><code contenteditable="true"><em>// stop current</em> $(<span>'#box'</span>).stop()</code></pre> <button type="button" class="code">Run Code</button> <pre><code contenteditable="true"><em>// stop all animation</em> $(<span>'#box'</span>).stop(true)</code></pre> <button type="button" class="code">Run Code</button> <pre><code contenteditable="true"><em>// stop current animation, goto end, clear queue</em> $(<span>'#box'</span>).stop(true, true)</code></pre> <button type="button" class="code">Run Code</button> <pre><code contenteditable="true"><em>// stop current animation</em> $(<span>'#box'</span>).stop(false, true)</code></pre> <button type="button" class="code">Run Code</button> </menu> <header> <h1>Очередь</h1> <h2>Пример работы с очередью и без анимировании элементов</h2> </header> <article> <div id="box"> <span>♠</span> <span>♣</span> <span class="red">♥</span> <span class="red">♦</span> </div> </article> <footer> ©copyright 2014 Anton Shevchuk — <a href="http://anton.shevchuk.name/jquery-book/">jQuery Book</a> </footer> <script type="text/javascript"> var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-1669896-2']); _gaq.push(['_trackPageview']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })(); </script> </div> </body> </html>
Заметка на будущее: если вы сделали выпадающее меню, и поигравшись с мышкой оно продолжает выпадать и исчезать, то значит надо вставить "stop()" в обработчик события
По умолчанию вся анимация над объектом складывается в очередь "fx", но с версии 1.7 можно указывать произвольную очередь:
$('#box') .animate({'left':'-=100'}, {queue:'x'}) // составляем очередь X .dequeue('x') // запускаем очередь X $('#box').stop('x') // останавливаем анимацию в очереди X
Для чего нам может понадобиться произвольная очередь? Да для распараллеливания анимации, чтобы мы могли запустить одну очередь анимации, и в любой другой момент запустить другую очередь, возможно, это заклад под игры? Но чего гадать, давайте пример посмотрим
<!DOCTYPE html> <html dir="ltr" lang="en-US"> <head> <meta charset="UTF-8"/> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Работа с произвольными очередями</title> <link rel="profile" href="http://gmpg.org/xfn/11"/> <link rel="shortcut icon" href="http://anton.shevchuk.name/favicon.ico"/> <link rel="stylesheet" href="css/styles.css"/> <script type="text/javascript" src="js/jquery.js"></script> <script type="text/javascript" src="js/code.js"></script> <script> $(function(){ var logX = $("#log-x"); var logY = $("#log-y"); var $box = $("#box"); logX.text($box.css('left')); logY.text($box.css('top')); var stepX = function(now, obj) { logX.text(Math.floor(now)+obj.unit) }; var stepY = function(now, obj) { logY.text(Math.floor(now)+obj.unit) }; $(document).keydown(function(e){ // 37 - left // 38 - up // 39 - right // 40 - down switch (e.keyCode) { case 37: $box.stop('x', true); $box.animate({'left':'-=100'}, {queue:'x', step:stepX}).dequeue('x'); break; case 38: $box.stop('y', true); $box.animate({'top':'-=100'}, {queue:'y', step:stepY}).dequeue('y'); break; case 39: $box.stop('x', true); $box.animate({'left':'+=100'}, {queue:'x', step:stepX}).dequeue('x'); break; case 40: $box.stop('y', true); $box.animate({'top':'+=100'}, {queue:'y', step:stepY}).dequeue('y'); break; } }) }); </script> <style> article { position: relative; } article.withbox { height: 600px; } #box { background: #55f; position: relative; margin: 10px; width: 80px; height: 80px; left:270px; top:0; } #box span { display: inline-block; background: #fff; font-size: 22px; line-height: 22px; text-align: center; width: 16px; margin: 6px 8px; padding: 2px; border: 1px solid #000; border-radius: 2px; -moz-border-radius: 2px; -webkit-border-radius: 2px; } .red { color:red; } </style> </head> <body> <div id="content" class="wrapper box"> <menu label="Try..."> <a href="animate.queue.html" title="go prev" class="button alignleft" rel="prev">← Prev </a> <a href="index.html" title="back to Index" class="button alignleft" rel="index">Index §</a> <a href="#" title="reload" class="button alignleft" onclick="window.location.reload();return false">Reload ¤</a> <a href="menu.drop-down.html" title="go next" class="button alignright" rel="next">Next →</a> <hr/> <pre><code contenteditable="true">$(<span>'#box'</span>).animate({ <span>'left'</span>:<span>'-=100'</span> }, {queue:'x', duration:2000}).dequeue('x')</code></pre> <button type="button" class="code">Left</button> <pre><code contenteditable="true">$(<span>'#box'</span>).animate({ <span>'left'</span>:<span>'+=100'</span> }, {queue:'x', duration:2000}).dequeue('x')</code></pre> <button type="button" class="code">Right</button> <pre><code contenteditable="true">$(<span>'#box'</span>).animate({ <span>'top'</span>:<span>'-=250'</span> }, {queue:'y', duration:2000}).dequeue('y')</code></pre> <button type="button" class="code">Up</button> <pre><code contenteditable="true">$(<span>'#box'</span>).animate({ <span>'top'</span>:<span>'+=250'</span> }, {queue:'y', duration:2000}).dequeue('y')</code></pre> <button type="button" class="code">Down</button> <pre><code contenteditable="true">$(<span>'#box'</span>).stop(<span>'x'</span>, true); $(<span>'#box'</span>).stop(<span>'y'</span>, true);</code></pre> <button type="button" class="code">Stop</button> </menu> <header> <h1>Произвольная очередь анимации</h1> <h2>Своя очередь, попробуйте использовать стрелочки на клавиатуре (← и →, ↑ и ↓)</h2> </header> <article> <p> X: <span id="log-x">0px</span> Y: <span id="log-y">0px</span> </p> </article> <article class="withbox"> <div id="box"> <span>♠</span> <span>♣</span> <span class="red">♥</span> <span class="red">♦</span> </div> </article> <footer> ©copyright 2014 Anton Shevchuk — <a href="http://anton.shevchuk.name/jquery-book/">jQuery Book</a> </footer> <script type="text/javascript"> var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-1669896-2']); _gaq.push(['_trackPageview']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })(); </script> </div> </body> </html>
Отключение
Иногда требуется отключить всю анимацию (к примеру, для отладки) воспользуйтесь следующей конструкцией:
jQuery.fx.off = true;