2016-01-31 13 views
8

Animare Div dopo che l'animazione Div precedente è stata completata utilizzando deferred object. Questo semplice metodo funziona con le due funzioni f1 e f2, tuttavia quando introduco f3 non riesce.Un'animazione Div dopo l'altra utilizzando oggetto posticipato

Esiste un modo migliore per raggiungere questo obiettivo utilizzando l'oggetto posticipato?

JSFiddle: https://jsfiddle.net/j0bgzjvd/

var deferred = $.Deferred(); 
 

 
function animationAgent(element, prevElement) { 
 
    $(prevElement).promise().done(function() { 
 
    return $(element).css("display", "block").animate({width:360},2000, "linear") 
 
    }); 
 
} 
 

 
function f1() { 
 
    animationAgent("#div1"); 
 
} 
 

 
function f2() { 
 
    animationAgent("#div2", "#div1"); 
 
} 
 

 
function f3() { 
 
    animationAgent("#div3", "#div2"); 
 
} 
 

 
deferred.resolve(); 
 
deferred.done([ f1, f2, f3 ]);
div { 
 
    width: 200px; 
 
    height: 200px; 
 
    background-color: red; 
 
    margin-bottom: 10px; 
 
    display: none; 
 
}
<script src="https://code.jquery.com/jquery-1.10.2.js"></script> 
 

 
<div id="div1"></div> 
 
<div id="div2"></div> 
 
<div id="div3"></div>

+0

si può aggiungere un frammento o bidone con questo problema? Qualche errore nella 'console'? –

+0

Si prega di vedere il JSFiddle aggiornato nel post. Nessun errore è presente nella console. Vorrei che i div animassero uno dopo l'altro in armonia, tuttavia come potete vedere la funzione 3 risulta in un disturbo nella sequenza di animazioni. Estrarre f3 consente a f1 e f2 di animare in sequenza - @MoshFeu – jcoulston2

+0

Controlla la risposta di seguito potrebbe aiutare. @ jcoulston2 –

risposta

1

Troverete più semplice a:

  • fanno animationAgent() in un semplice, funzione di operaio promessa-ritorno che conosce solo l'elemento che anima e nulla sulla sequenza in cui deve essere utilizzato (ovvero omettere),
  • disporre le funzioni f1(), f2() e f3(), per restituire la promessa restituita loro dal animationAgent().

Quindi avete le basi per costruire una sequenza di animazione affidabile.

function animationAgent(element) { 
    return $(element).css("display", "block").animate({width:360}, 2000, "linear").promise(); 
} 
function f1() { 
    return animationAgent("#div1"); 
} 
function f2() { 
    return animationAgent("#div2"); 
} 
function f3() { 
    return animationAgent("#div3"); 
} 

f1().then(f2).then(f3); 

DEMO

alternativa, costruire la catena .then meccanicamente da un array di riferimenti funzionali:

function animationAgent(element) { 
    return $(element).css("display", "block").animate({width:360}, 2000, "linear").promise(); 
} 
function f1() { 
    return animationAgent("#div1"); 
} 
function f2() { 
    return animationAgent("#div2"); 
} 
function f3() { 
    return animationAgent("#div3"); 
} 

[f1, f2, f3].reduce(function(promise, fn) { 
    return promise.then(function() { 
     return fn(); 
    }); 
}, $.when()); 

DEMO

O, come i tre animazioni sono identico, y ou può evitare la necessità di singole funzioni costruendo la catena .then da una matrice di selettori di elementi e chiamando direttamente animationAgent():

function animationAgent(element) { 
    return $(element).css("display", "block").animate({width:360}, 2000, "linear").promise(); 
} 

['#div1', '#div2', '#div3'].reduce(function(promise, selector) { 
    return promise.then(function() { 
     return animationAgent(selector); 
    }); 
}, $.when()); 

DEMO

0

mai pensato di usare le richiamate nella funzione di animazione?

Ecco un esempio con fadeOut: https://jsfiddle.net/0r7e2wco/

fadeOutInTurn([ 
    $("#div1"), 
    $("#div2"), 
    $("#div3"), 
    $("#div4"), 
]); 

//Fades out elements one after another 
function fadeOutInTurn(elements) { 
    var x = 0; 
    function animate() { 
     $(elements[x]).fadeOut(3000, function() { 
      if(x < elements.length - 1) { 
       x++; 
       animate(); 
      } 
     }); 
    } 
    animate(); 
} 
+1

Penso che lo voglia usare 'oggetto differito' .. –

+0

" C'è un modo migliore per raggiungerlo? " Immaginavo che volesse sapere modi migliori per animare gli elementi uno dopo l'altro. – seahorsepip

+0

Se vuole usare un oggetto deffered dovrebbe usare notify() e progress() invece di resolve() e done(), in questo modo un oggetto deffered può essere usato un numero illimitato di volte ^^ Ma non capisco perché qualcuno userebbe un pattern deffered per animare alcuni elementi a sua volta ... – seahorsepip

0

non sono sicuro, ma penso che questo è ciò che si desidera.

esempio fiddle

Penso che si spera deferred.done() eseguirà f1, f2, f3 uno dopo altro bene fa che lavorare. ma non aspetta che le animazioni chiamate all'interno di queste funzioni terminino prima di chiamare la funzione successiva.

provare a registrare la funzione chiamate su console utilizzando console.log() e lo saprai.

qui è la versione aggiornata di codice javascript -

var deferred = $.Deferred(); 
var lock = 1; 

function animationAgent(element, id, prevElement) { 
    var interval; 
    var flag = 0; 
    if (id != lock) { 
    interval = setInterval(function() { 
     if (id == lock) { 
     clearInterval(interval); 
     animationAgent(element, id, prevElement); 
     } 
    }, 1000); 
    }else{ 
    $(prevElement).promise().done(function() { 
     lock++; 
     return $(element).css("display", "block").animate({ 
     width: 360 
     }, 2000, "linear"); 
    }); 
    } 
} 

function f1() { 
    return animationAgent("#div1", 1); 
} 

function f2() { 
    return animationAgent("#div2", 2, "#div1"); 
} 

function f3() { 
    return animationAgent("#div3", 3, "#div2"); 
} 

deferred.resolve(); 
deferred.done([f1, f2, f3]); 
Problemi correlati