then - ¿Cómo puedo encadenar o poner en cola funciones personalizadas usando JQuery?
jquery ui animate (15)
Tengo varias funciones: hacer diferentes animaciones a diferentes partes del HTML. Me gustaría encadenar o poner en cola estas funciones para que ejecuten las animaciones secuencialmente y no al mismo tiempo.
Estoy intentando automatizar múltiples eventos en secuencia para que parezca que un usuario ha estado haciendo clic en diferentes botones o enlaces.
Probablemente podría hacer esto usando funciones de devolución de llamada, pero luego tendría que extraer todas las animaciones de las diferentes funciones y reagruparme en el patrón correcto.
¿Ayuda la "cola" de jquery? No pude entender la documentation de la cola.
Ejemplo, JQuery:
function One() {
$(''div#animateTest1'').animate({ left: ''+=200'' }, 2000);
}
function Two() {
$(''div#animateTest2'').animate({ width: ''+=200'' }, 2000);
}
// Call these functions sequentially so that the animations
// in One() run b/f the animations in Two()
One();
Two();
HTML:
<div id="animatetest" style="width:50px;height:50px;background-color:Aqua;position:absolute;"></div>
<div id="animatetest2" style="width:50px;height:50px;background-color:red;position:absolute;top:100px;"></div>
Gracias.
EDITAR: Lo probé con timers pero pensé que había una mejor manera de hacerlo.
EDIT # 2:
Déjame ser más específico. Tengo varias funciones destinadas a hacer clic y colocar eventos en diferentes elementos de la página. Normalmente, estas funciones no tienen nada que ver entre sí (no se refieren entre sí). Me gustaría simular que un usuario pase por estos eventos sin cambiar el código de mis funciones existentes.
¿Qué tal algo así?
var f1 = function() {return $(SELECTOR1).animate({ ''prop'': ''value'' }, 1000)};
var f2 = function() {return $(SELECTOR2).animate({ ''prop'': ''value'' }, 1000)};
var f3 = function() {return $(SELECTOR3).animate({ ''prop'': ''value'' }, 1000)};
$.when(f1).then(f2).then(f3);
@TrippRitter tiene que adjuntar .call a la devolución de llamada
One = function(callback){
$(''div#animateTest1'').animate({ left: ''+=200'' }, 2000, function(){
if(typeof callback == ''function''){
callback.call(this);
}
});
}
Two = function(){
$(''div#animateTest2'').animate({ width: ''+=200'' }, 2000);
}
One(function(){
Two();
});
pero es lo mismo que hacer lo siguiente
$(''div#animateTest1'')
.animate({ left: ''+=200'' }, 2000,
function(){
Two();
});
Two = function(){
$(''div#animateTest2'').animate({ width: ''+=200'' }, 2000);
}
Copiar y pegar ............ 7/9/2013
<!doctype html>
<html lang="en">
enter code here<head>
<meta charset="utf-8">
<title>jQuery.queue demo</title>
<style>
div { margin:3px; width:40px; height:40px;
position:absolute; left:0px; top:30px;
background:green; display:none; }
div.newcolor { background:blue; }
</style>
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
</head>
<body>
<button id="start">Start</button>
<button id="stop">Stop</button>
<div></div>
<script>
$("#start").click(function () {
$("div").show("slow");
$("div").animate({left:''+=200''},5000);
jQuery.queue( $("div")[0], "fx", function () {
$(this).addClass("newcolor");
jQuery.dequeue( this );
});
$("div").animate({left:''-=200''},1500);
jQuery.queue( $("div")[0], "fx", function () {
$(this).removeClass("newcolor");
jQuery.dequeue( this );
});
$("div").slideUp();
});
$("#stop").click(function () {
jQuery.queue( $("div")[0], "fx", [] );
$("div").stop();
});
</script>
</body>
</html>
Creé una serie de funciones y agregué todas las funciones que desea poner en cola.
Luego anexaré una llamada a función que recorre la matriz y llama cada función al evento a través de jQuery.
Probablemente puedas crear un complemento muy simple para jQuery que también pueda manejar esto internamente.
El código jQuery Queue no está tan bien documentado como podría ser, pero la idea básica es esta:
$("#some_element").queue("namedQueue", function() {
console.log("First");
var self = this;
setTimeout(function() {
$(self).dequeue("namedQueue");
}, 1000);
});
$("#some_element").queue("namedQueue", function() {
console.log("Second");
var self = this;
setTimeout(function() {
$(self).dequeue("namedQueue");
}, 1000);
});
$("#some_element").queue("namedQueue", function() {
console.log("Third");
});
$("#some_element").dequeue("namedQueue");
Si ejecuta este código, verá "Primero" en la consola, una pausa de 1s, vea "Segundo" en la consola, otra pausa de 1s, y finalmente vea "Tercero" en la consola.
La idea básica es que puede tener cualquier número de colas con nombre vinculadas a un elemento. Elimina un elemento de la cola llamando a la cola. Puede hacerlo usted mismo manualmente tantas veces como quiera, pero si desea que la cola se ejecute automáticamente, simplemente puede llamar a la cola dentro de la función de cola.
Las animaciones en jQuery se ejecutan dentro de una cola llamada fx
. Cuando anima un elemento, automáticamente agrega la nueva animación en la cola y las llamadas dequeue si no hay animaciones actualmente en ejecución. Puede insertar sus propias devoluciones de llamada en la cola fx
si lo desea; solo tendrá que llamar a dequeue
manualmente al final (como con cualquier otro uso de la cola).
En cuanto al intervalo de animación ya definido en 2000 ms, puede hacer la segunda llamada con retraso en 2000 ms:
One();
SetTimeout(function(){
Two();
}, 2000);
En lugar de crear una función de forma simple, está aquí:
$(''#main'').animate({ "top": "0px"}, 3000, function()
{ $(''#navigation'').animate({ "left": "100px"}, 3000, function()
{
alert("Call after first and second animation is completed.");
})
}
);
Por lo tanto, Jquery de forma predeterminada proporciona la cola que ejecuta la función uno por uno.
En uno de mis proyectos web, tuve que realizar varias secuencias de acciones dependiendo de qué evento se disparó. Lo hice usando devoluciones de llamada (algo así como el patrón Visitor). Creé un objeto para envolver cualquier función o grupo de acciones. Luego pondría en cola esas envolturas; una matriz funciona bien. Cuando el evento se disparaba, repetía la matriz, llamando al método especializado de mi objeto que recibía una devolución de llamada. Esa devolución de llamada activó mi iteración para continuar.
Para ajustar una función, necesita conocimiento de la función aplicar . La función aplicar toma un objeto para el alcance y una matriz de argumentos. De esta forma, no necesita saber nada sobre las funciones que está ajustando.
Lo siguiente funcionará y no dará error si la devolución de llamada es nula:
function One(callback)
{
$(''div#animateTest1'').animate({ left: ''+=200'' }, 2000,
function()
{
if(callback != null)
{
callback();
}
}
);
}
function Two()
{
$(''div#animateTest2'').animate({ width: ''+=200'' }, 2000);
}
var callback = function(){ Two(); };
One(callback);
Me gustaría ejecutar el segundo como una función de devolución de llamada:
$(''div#animateTest1'').animate({ left: ''+=200'' }, 2000, function(){
two();
});
que se ejecutarían dos () cuando termine la primera animación, si tienes más animaciones en la cola temporizada para esos casos, uso el plugin de jquery timer en lugar de setTimeout (), que en algunos casos resulta muy útil.
Si bien la respuesta de Yehuda Katz es técnicamente correcta, se hinchará muy rápido con animaciones más grandes y complejas.
Hice un complemento para situaciones como la suya que permite funciones de cola (con pausa y reanudar si es necesario).
demo: https://jessengatai.github.io/okaynowthis.js/
La solución a su problema usando okaynowthis.js se vería así:
$(''window'').load(function(){
// keyframe 1
$(''body'').okaynowthis(''keyframe'',0,function(){
$(''div#animateTest1'').animate({ left: ''+=200'' }, 2000);
// + anything else you want to do
// keyframe 2 (with 2 seconds delay from keyframe 1)
}).okaynowthis(''keyframe'',2000,function(){
$(''div#animateTest2'').animate({ left: ''+=200'' }, 2000);
// + anything else you want to do
});
});
Solución realmente simple.
function One() {
$(''div#animateTest1'').animate({ left: ''+=200'' }, 2000, Two);
}
function Two() {
$(''div#animateTest2'').animate({ width: ''+=200'' }, 2000);
}
// Call these functions sequentially so that the animations
// in One() run b/f the animations in Two()
One();
//We no longer need to call Two, as it will be called when 1 is completed.
//Two();
Suponiendo que desea mantener One
y Two
como funciones separadas, podría hacer algo como esto:
function One(callback) {
$(''div#animateTest1'').animate({ left: ''+=200'' }, 2000,
function(e) { callback(); });
}
function Two() {
$(''div#animateTest2'').animate({ width: ''+=200'' }, 2000);
}
// Call these functions sequentially so that the animations
// in One() run b/f the animations in Two()
One(Two);
Una forma más segura y 100% de trabajo es usar una variable y ramas if. En el siguiente ejemplo, realizamos 4 trabajos que demoran 1 segundo, luego del trabajo que queremos que ejecute la función f2.
<html><body>
<div id="a" class="a" />
<script type="text/javascript">
var jobs = 0;
function f1() {
job();
job();
job();
job();
};
function f2() {
if(jobs >3)
l("f2");
};
<!------------------------- ->
function job() {
setTimeout(function() {
l("j");
jobs+=1;
f2();
}, 1000);
}
function l(a) {
document.getElementById(''a'').innerHTML+=a+"<br />";
};
f1();
</script></body></html>
$(''div#animateTest1'').animate({left: ''+=200''},2000,
function(){
$(''div#animateTest2'').animate({ width: ''+=200'' }, 2000);
}
);