Animazione sincrona JQuery

In molti casi desidero che l’animazione sia eseguita in modo sincrono. Soprattutto quando desidero creare una serie di animazioni sequenziali.

C’è un modo semplice per fare una chiamata di funzione animate jQuery sincrona?

L’unico modo in cui ho pensato è di impostare un flag vero quando l’animazione è finita e aspettare questo flag.

jQuery non può creare animazioni sincrone.

Ricorda che JavaScript viene eseguito sul thread dell’interfaccia utente del browser.

Se crei un’animazione sincrona, il browser si bloccherà fino al termine dell’animazione.

Perché hai bisogno di fare questo?

Probabilmente dovresti usare il parametro callback di jQuery e continuare il codice del metodo nel callback, in questo modo:

 function doSomething() { var thingy = whatever; //Do things $('something').animate({ width: 70 }, function() { //jQuery will call this method after the animation finishes. //You can continue your code here. //You can even access variables from the outer function thingy = thingy.fiddle; }); } 

Questo è chiamato una chiusura.

Penso che dovresti dare un’occhiata al metodo jQuery queue () .

Non solo il doc di queue () spiega che le animazioni di jQuery in realtà non bloccano l’interfaccia utente e in realtà le accodano una dopo l’altra.

Fornisce anche un modo per rendere sequenziali le tue animazioni e le chiamate di funzione (questa è la mia migliore comprensione di cosa intendi con ” sincrono “), come:

 $("#myThrobber") .show("slow") // provide user feedback .queue( myNotAnimatedMethod ) // do some heavy duty processing .hide("slow"); // provide user feedback (job's myNotAnimatedMethod() { // or animated, just whatever you want anyhow... // do stuff // ... // tells #myThrobber's ("this") queue your method "returns", // and the next method in the queue (the "hide" animation) can be processed $(this).dequeue(); // do more stuff here that needs not be sequentially done *before* hide() // } 

Questo è ovviamente eccessivo con l’elaborazione asincrona; ma se il tuo metodo è in realtà un semplice vecchio metodo javascript sincrono, quello potrebbe essere il modo per farlo.

Spero che questo aiuti, e mi dispiace per il mio povero inglese …

jQuery fornisce un callback “step” per il suo metodo .animate (). Puoi collegarti a questo per fare animazioni sincrone:

 jQuery('#blat').animate({ // CSS to change height: '0px' }, { duration: 2000, step: function _stepCallback(now,opts) { // Stop browser rounding errors for bounding DOM values (width, height, margin, etc.) now = opts.now = Math.round(now); // Manipulate the width/height of other elements as 'blat' is animated jQuery('#foo').css({height: now+'px'}); jQuery('#bar').css({width: now+'px'}); }, complete: function _completeCallback() { // Do some other animations when finished... } } 

Sono d’accordo con @SLaks su questo. Dovresti utilizzare le callback di jQuery per le animazioni fornite per creare l’animazione sincrona. Puoi essenzialmente prendere tutto ciò che hai per la tua animazione corrente e dividerlo in questo modo:

 $yourClass = $('.yourClass'); $yourClass.animate({ width: "70%" }, 'slow', null, function() { $yourClass.animate({ opacity: 0.4 }, 'slow', null, function() { $yourClass.animate({ borderWidth: "10px" }); }); }); 

Ecco un modulo che ho messo insieme un po ‘indietro per aiutare a eseguire le animazioni in sequenza.

Uso:

 var seq = [ { id: '#someelement', property:'opacity', initial: '0.0', value:'1.0', duration:500 }, { id: '#somethingelse', property:'opacity', value:'1.0', duration: 500 } ]; Sequencer.runSequence(seq); 

 var Sequencer = (function($) { var _api = {}, _seq = {}, _seqCount = 0, _seqCallback = {}; function doAnimation(count, step) { var data = _seq[count][step], props = {}; props[data.property] = data.value $(data.id).animate(props, data.duration, function() { if (step+1 < _seq[count].length) { doAnimation(count, ++step); } else { if (typeof _seqCallback[count] === "function") { _seqCallback[count](); } } }); } _api.buildSequence = function(id, property, initial, steps) { var newSeq = [], step = { id: id, property: property, initial: initial }; $.each(steps, function(idx, s) { step = {}; if (idx == 0) { step.initial = initial; } step.id = id; step.property = property; step.value = s.value; step.duration = s.duration; newSeq.push(step); }); return newSeq; } _api.initSequence = function (seq) { $.each(seq, function(idx, s) { if (s.initial !== undefined) { var prop = {}; prop[s.property] = s.initial; $(s.id).css(prop); } }); } _api.initSequences = function () { $.each(arguments, function(i, seq) { _api.initSequence(seq); }); } _api.runSequence = function (seq, callback) { //if (typeof seq === "function") return; _seq[_seqCount] = []; _seqCallback[_seqCount] = callback; $.each(seq, function(idx, s) { _seq[_seqCount].push(s); if (s.initial !== undefined) { var prop = {}; prop[s.property] = s.initial; $(s.id).css(prop); } }); doAnimation(_seqCount, 0); _seqCount += 1; } _api.runSequences = function() { var i = 0. args = arguments, runNext = function() { if (i+1 < args.length) { i++; if (typeof args[i] === "function") { args[i](); runNext(); } else { _api.runSequence(args[i], function() { runNext(); }); } } }; // first we need to set the initial values of all sequences that specify them $.each(arguments, function(idx, seq) { if (typeof seq !== "function") { $.each(seq, function(idx2, seq2) { if (seq2.initial !== undefined) { var prop = {}; prop[seq2.property] = seq2.initial; $(seq2.id).css(prop); } }); } }); _api.runSequence(arguments[i], function (){ runNext(); }); } return _api; }(jQuery)); 

jQuery può creare animazioni sincrone. Controllalo:

 function DoAnimations(){ $(function(){ $("#myDiv").stop().animate({ width: 70 }, 500); $("#myDiv2").stop().animate({ width: 100 }, 500); }); } 

Mi sono imbattuto in questo http://lab.gracecode.com/motion/ Davvero facile da usare e funziona alla grande in combinazione con jquery.

MODIFICA I collegamenti sembrano morti. Se ho seguito la traccia di quelli archiviati correttamente, il codice è su https://github.com/feelinglucky/motion