2012-01-09 23 views
86

Desde añadí algunos scrollTop -Animación, algunas partes de mi devolución de llamada consigo llamado dos veces:de devolución de llamada de .animate() se llama dos veces jQuery

$('html, body').animate({scrollTop: '0px'}, 300,function() { 
    $('#content').load(window.location.href, postdata, function() {     
     $('#step2').addClass('stepactive').hide().fadeIn(700, function() { 
      $('#content').show('slide',800);      
     }); 
    }); 
}); 

sólo parece repetir el .show(), al menos yo no' Tengo la impresión de que llamaron por segunda vez al load() o al .fadeIn(). El .show() se repite tan pronto como termina por primera vez. ¡Configurar la velocidad de animación de scrollTop a 0 no ayudó por cierto!

Supongo que tiene algo que ver con la cola de animación, pero no puedo encontrar la manera de encontrar una solución, especialmente por qué esto está sucediendo.

Respuesta

131

animate llama a su devolución de llamada una vez para cada elemento en el conjunto de llamar animate en:

Si suministra, las start, step, progress, complete, done, fail y always devoluciones de llamada están llamados a por elemento base ...

Dado que está animando dos elementos (el elemento html y el elemento body), obtendrá dos devoluciones de llamada. (Para cualquiera que se pregunte qué el PO está animando dos elementos, que se debe a la animación trabaja en body en algunos navegadores, pero en html en otros navegadores.)

Para obtener una sola de devolución de llamada cuando la animación se ha completado , los animate documentos que apuntan a utilizar el método promise para obtener una promesa para la cola de animación, a continuación, utilizando then que hacer cola la devolución de llamada:

$("html, body").animate(/*...*/) 
    .promise().then(function() { 
     // Animation complete 
    }); 

(Nota: Kevin B señaló esto in his answer cuando se hizo la pregunta por primera vez. No lo hice hasta cuatro años después cuando noté que faltaba, lo agregué y ... luego vi la respuesta de Kevin. Por favor, dale a su respuesta el amor que se merece. Supuse que esta es la respuesta aceptada, me dejo en)

He aquí un ejemplo que muestra tanto las devoluciones de llamada de elementos individuales, y la devolución de llamada conclusión general:.

jQuery(function($) { 
 

 
    $("#one, #two").animate({ 
 
    marginLeft: "30em" 
 
    }, function() { 
 
    // Called per element 
 
    display("Done animating " + this.id); 
 
    }).promise().then(function() { 
 
    // Called when the animation in total is complete 
 
    display("Done with animation"); 
 
    }); 
 

 
    function display(msg) { 
 
    $("<p>").html(msg).appendTo(document.body); 
 
    } 
 
});
<div id="one">I'm one</div> 
 
<div id="two">I'm two</div> 
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

+2

Sí, esa fue la razón y en realidad no recuerdo por qué alguna vez escribí 'html, body'. Es hora de volver a encender mi cerebro.Gracias – Anonymous

+20

Probablemente porque animar solo html no funcionará en Webkit, y el cuerpo no funcionará en Opera. Usar ambos asegurará que siempre funcione, pero activará la devolución de llamada dos veces en Firefox. (Pude haber equivocado los navegadores ...) –

+2

'html' es necesario para IE, y la devolución de llamada se activará dos veces para la mayoría de los otros navegadores. Estoy tratando de encontrar una solución al mismo problema. –

159

Para obtener una devolución de llamada única para la finalización de animaciones de elementos múltiples, use objetos diferidos.

$(".myClass").animate({ 
    marginLeft: "30em" 
}).promise().done(function(){ 
    alert("Done animating"); 
}); 

Ver la API de jQuery para una descripción detallada de la Promise y Deferred Objects.

+11

Esto se debe seleccionar como una respuesta correcta ... – Foxhoundn

+0

Esto se resuelve el problema sobre lo que queremos hacer al finalizar la animación, pero se trata de dos veces llamar y obtuvimos +1 para eso, pero no sé si el proceso animado es llamado dos veces o no ?! – QMaster

+1

El proceso animado no se llama dos veces, la devolución de llamada se llama una vez para cada elemento seleccionado. Entonces, si selecciona 8 elementos de lista y los anima a la izquierda, la devolución de llamada se ejecutará 8 veces. Mi solución te da una única devolución de llamada para cuando terminen los 8. –

Cuestiones relacionadas