2016-01-31 9 views
8

Animuj Div po zakończeniu poprzedniej animacji Div przy użyciu deferred object. Ta prosta metoda działa z dwiema funkcjami: f1 i f2, jednak po wprowadzeniu f3 kończy się niepowodzeniem.Jedna animacja Div po kolejce z odroczonym obiektem

Czy istnieje lepszy sposób, w jaki mogę to osiągnąć za pomocą odroczonego obiektu?

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

można dodać fragment lub pojemnik z tym problemem? Jakieś błędy w 'konsoli'? –

+0

Zobacz JSFiddle zaktualizowany we wpisie. Brak błędów w konsoli. Chciałbym, aby divy animowały jeden po drugim w harmonii, jednak jak widać funkcja 3 powoduje zakłócenie sekwencji animacji. Wyciągnięcie f3 pozwala na animację sekwencji f1 i f2 w sekwencji - @MoshFeu – jcoulston2

+0

Sprawdź, czy odpowiedź poniżej może pomóc. @ jcoulston2 –

Odpowiedz

1

Znajdziesz to prościej:

  • zrobić animationAgent() w prosty, obietnica powrotu funkcji pracownika, który wie tylko o elemencie to ożywia i nic o sekwencji, w której ma być używana (tj. pomiń prevElement),
  • zorganizować funkcje f1(), f2() i f3(), aby zwrócić obietnicę zwróconą im przez animationAgent().

Masz wtedy podstawę do stworzenia niezawodnej sekwencji animacji.

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

Alternatywnie skonstruować łańcuch .Następnie mechanicznie z tablicy odniesienia funkcyjne:

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

albo, jak trzy animacje identyczne, y ou można uniknąć potrzeby poszczególnych funkcji poprzez budowę łańcucha .Następnie z tablicy selektorów elementu i wywołanie animationAgent() bezpośrednio:

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

kiedykolwiek myślał o użyciu wywołania zwrotne w funkcji animacji?

Oto przykład z 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

Myślę, że chce tego używać "obiektu odroczonego" .. –

+0

"Czy istnieje lepszy sposób, w jaki mogę to osiągnąć?" Sądziłem, że chce poznać lepsze sposoby animowania elementów jeden po drugim. – seahorsepip

+0

Jeśli chce użyć obiektu z opcją, powinien użyć funkcji notify() i progress() zamiast resolve() i done(), w ten sposób obiekt przerwany może zostać użyty w nieograniczonej ilości razy ^^ Ale nie rozumiem dlaczego ktokolwiek użyłby jakiegoś oplecionego wzorca do animowania niektórych elementów ... – seahorsepip

0

nie wiem, ale myślę, że to, co chcesz.

przykład fiddle

myślę, że mają nadzieję deferred.done() wykona f1, f2, f3 jedna po drugiej jak to robi, że działa. ale nie czeka na zakończenie animacji wywoływanych w tych funkcjach przed wywołaniem następnej funkcji.

spróbuj zarejestrować wywołania funkcji na konsoli przy użyciu console.log(), a będziesz wiedzieć.

tutaj jest zaktualizowany kod 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]);