JQuery animation synchrone

dans de nombreux cas, je souhaite que l'animation soit exécutée de façon synchrone. Surtout quand je veux faire une série séquentielle des animations.

Est-il un moyen facile de faire un jQuery animate appel de la fonction synchrone?

la seule façon dont j'ai pensé est de mettre un vrai drapeau quand l'animation est terminée et d'attendre ce drapeau.

19
demandé sur Elazar Leibovich 2009-10-20 15:53:57

7 réponses

jQuery ne peut pas faire des animations synchrones.

rappelez-vous que JavaScript s'exécute sur le thread de L'interface utilisateur du navigateur.

si vous faites une animation synchrone, le navigateur gèlera jusqu'à la fin de l'animation.

Pourquoi avez-vous besoin de faire cela?

Vous devriez probablement utiliser le paramètre callback de jQuery et continuer votre code de méthode dans le callback, comme ceci:

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;
    });
}

C'est ce qu'on appelle une fermeture.

24
répondu SLaks 2009-12-08 18:09:47

je pense que vous devriez jeter un coup d'oeil à la jQuery file() méthode.

non seulement le doc de queue () explique que les animations jQuery ne bloquent pas vraiment L'interface utilisateur, et qu'elles les mettent en file d'attente les unes après les autres.

Il fournit également un moyen de rendre vos animations et des appels de fonction séquentielle (c'est mon meilleure compréhension de ce que vous entendez par "synchrone"), de la forme:

$("#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()
    // 
}  

c'est évidemment exagéré avec l'asynchrone traitement; mais si votre méthode est en fait une ancienne méthode javascript synchrone, cela pourrait être la façon de le faire.

j'Espère que cela aide, et désolé pour mon mauvais anglais...

6
répondu Alain BECKER 2010-04-26 19:36:06

jQuery fournit un callback" step " pour its .animate() de la méthode. Vous pouvez accrocher dans cette pour faire synchrone animations:

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...
  }
}
2
répondu shuckster 2009-12-08 17:53:28

je suis d'accord avec @SLaks sur celui-ci. Vous devriez utiliser les callbacks de jQuery pour des animations données pour créer votre animation synchrone. Vous pouvez essentiellement prendre tout ce que vous avez pour votre animation actuelle et la diviser comme suit:

$yourClass = $('.yourClass');
$yourClass.animate({
    width: "70%"
}, 'slow', null, function() {
    $yourClass.animate({
        opacity: 0.4
    }, 'slow', null, function() {
        $yourClass.animate({
            borderWidth: "10px"
        });
    });
});
1
répondu Corey Ballou 2009-10-20 12:57:53

voici un module que j'ai mis en place il y a quelques temps pour aider à exécuter les animations de façon séquentielle.

Utilisation:

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));
0
répondu Jason Miesionczek 2011-10-07 16:06:00

jQuery peut faire des animations synchrones. Check this out:

function DoAnimations(){
  $(function(){
    $("#myDiv").stop().animate({ width: 70 }, 500);
    $("#myDiv2").stop().animate({ width: 100 }, 500);
  });
}
0
répondu Ben 2012-05-30 20:11:43

je suis tombé sur ce http://lab.gracecode.com/motion/ Vraiment facile à utiliser et fonctionne très bien en combinaison avec jquery.

EDIT Les liens semble morte. Si j'ai suivi la piste ces archives wayback correctement, le code est à https://github.com/feelinglucky/motion

0
répondu John van Dijk 2015-01-22 20:35:13