Jak animować w jQuery bez układania wywołań zwrotnych?
Powiedzmy, że mam trzy divy i chciałbym, aby każdy z nich animował po zakończeniu poprzedniego. Obecnie piszę to:
$('div1').fadeOut('slow', function() {
$('div2').fadeOut('slow', function() {
$('div3').fadeOut('slow');
});
});
Co jest brzydkie, ale do opanowania.
Teraz wyobraź sobie, że mam 10 różnych animacji, które muszą się odbywać jedna po drugiej na różnych elementach . Nagle kod staje się tak niezgrabny, że jest niezwykle trudny do zarządzania...
Oto pseudokod do tego, co chcę zrobić:
$('div1').fadeOut('slow' { delay_next_function_until_done: true } );
$('div2').fadeOut('slow' { delay_next_function_until_done: true } );
$('div3').animate({ top: 500 }, 1000 );
Jak to osiągnąć?
7 answers
Jeśli używasz najnowszej wersji jQuery, użyj obietnic animacji:
$('div1').fadeOut('slow').promise().pipe(function() {
return $('div2').fadeOut('slow');
}).pipe(function() {
return $('div3').animate({ top: 500 }, 1000 );
});
Możesz zrobić to generycznie:
$.chain = function() {
var promise = $.Deferred().resolve().promise();
jQuery.each( arguments, function() {
promise = promise.pipe( this );
});
return promise;
};
var animations = $.chain(function() {
return $('div1').fadeOut('slow');
}, function() {
return $('div2').fadeOut('slow');
}, function() {
return $('div3').animate({ top: 500 }, 1000 );
});
$.when( animations ).done(function() {
// ALL ANIMATIONS HAVE BEEN DONE IN SEQUENCE
});
Wciąż jest wiele zamknięć funkcji, ale taka jest natura Javascript. Jednak jest to o wiele bardziej naturalne i o wiele bardziej elastyczne przy użyciu Deferreds / Promises, ponieważ unikasz wywołań zwrotnych "Incepcja".
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-26 15:21:02
Robię to, dzięki tej metodzie możesz umieścić wszystkie div, jak chcesz, tylko dodając lub usuwając elementy w liście var, możesz również zmienić ich kolejność i nie musisz się martwić o Czas opóźnienia.
var list = [ '#div1', '#div2', '...' ];
var i = 0;
function fade(cb) {
if (i < list.length) {
$(list[i]).fadeOut('slow', function() {
i++;
fade(cb);
});
} else {
cb && cb();
}
}
fade();
Możesz również dodać wywołanie zwrotne po zakończeniu procesu
fade(function(){alert('end')});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-29 10:58:10
Kiedy funkcje kończące lub wywołania zwrotne są zagnieżdżane zbyt głęboko lub kod jest powtarzany w kółko, mam tendencję do myślenia o rozwiązaniu tabeli danych ze wspólną funkcją:
function fadeSequence(list) {
var index = 0;
function next() {
if (index < list.length) {
$(list[index++]).fadeOut(next);
}
next();
}
var fades = ["div1", "div2", "div3", "div4", "div5"];
fadeSequence(fades);
I, jeśli chcesz innego rodzaju animacji dla niektórych elementów, możesz utworzyć tablicę obiektów, które opisują, co każda kolejna animacja ma być. Możesz umieścić tyle szczegółów w tablicy obiektów, ile było potrzebne. Możesz nawet mieszać animacje z innymi synchroniczne wywołania metody jQuery w ten sposób:
function runSequence(list) {
var index = 0;
function next() {
var item, obj, args;
if (index < list.length) {
item = list[index++];
obj = $(item.sel);
args = item.args.slice(0);
if (item.sync) {
obj[item.type].apply(obj, args);
setTimeout(next, 1);
} else {
args.push(next);
obj[item.type].apply(obj, args);
}
}
}
next();
}
// sequence of animation commands to run, one after the other
var commands = [
{sel: "#div2", type: "animate", args: [{ width: 300}, 1000]},
{sel: "#div2", type: "animate", args: [{ width: 25}, 1000]},
{sel: "#div2", type: "fadeOut", args: ["slow"]},
{sel: "#div3", type: "animate", args: [{ height: 300}, 1000]},
{sel: "#div3", type: "animate", args: [{ height: 25}, 1000]},
{sel: "#div3", type: "fadeOut", args: ["slow"]},
{sel: "#div4", type: "fadeOut", args: ["slow"]},
{sel: "#div1", type: "fadeOut", args: ["slow"]},
{sel: "#div5", type: "css", args: ["position", "absolute"], sync: true},
{sel: "#div5", type: "animate", args: [{ top: 500}, 1000]}
];
runSequence(commands);
A oto demo tej drugiej opcji: http://jsfiddle.net/jfriend00/PEVEh/
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-29 08:10:01
Jednym ze sposobów, aby to zrobić, byłoby napisanie własnej funkcji pomocniczej, w ten sposób:
$.fn.sequentialFade = function() {
if(this.length > 0) {
var $set = $(this);
$set.eq(0).fadeOut(function() {
$set.slice(1).sequentialFade();
});
}
}
I używaj go tak:
$('.div1, .div2. .div3').sequentialFade();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-29 07:01:57
Spróbuj czegoś takiego:
$( 'div1' ).fadeOut();
$( 'div2' ).delay( 500 ).fadeOut();
$( 'div3' ).delay( 1000 ).fadeOut();
Dostosuj czas w razie potrzeby
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-29 06:53:03
Użyj tego:
$('#div1, #div2, #div3').each(function(index){
$(this).delay(1000 * index).hide(1000);
});
Jeśli możesz dać <div>
S klasę:
$('.forHide').each(function(index, value){
$(this).delay(1000 * index).hide(1000);
});
- pierwszy element zanika po 1000 * 0 = od razu z animacją trwającą jedną sekundę.
- drugi element zanika po 1000 * 1 = jedna sekunda z animacją jednej sekundy.
- trzeci element zanika po 1000 * 2 = dwie sekundy z animacją jednej sekundy.
- ...
- ...
- N element zanika po 1000 * N = N sekund z animacją trwającą jedną sekundę.
Live DEMO
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-29 07:19:04
Callback to przyjaciel, nie odpychaj go. Istnieją sposoby na ich uproszczenie. Oto jeden z nich
$('div1').fadeOut('slow', div2)
function div3() { $('div3').fadeOut('slow'); }
function div2() { $('div2').fadeOut('slow', div3); }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-29 08:34:21