【问题标题】:JQuery synchronous animationjQuery同步动画
【发布时间】:2010-12-08 07:43:21
【问题描述】:

在很多情况下,我希望动画能够同步执行。特别是当我想制作一系列连续动画时。

有没有一种简单的方法可以使 jQuery animate 函数调用同步?

我想到的唯一方法是在动画完成时设置一个标志为真并等待这个标志。

【问题讨论】:

    标签: jquery asynchronous jquery-animate synchronous


    【解决方案1】:

    jQuery 无法制作同步动画。

    请记住,JavaScript 在浏览器的 UI 线程上运行。

    如果您制作同步动画,浏览器将冻结,直到动画完成。

    为什么需要这样做?

    您可能应该使用 jQuery 的回调参数并在回调中继续您的方法代码,如下所示:

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

    这称为闭包。

    【讨论】:

    • 我认为您可以使用 setTimeout 从 UI 线程中逃脱,因此我绝对可以在 setTimeout 函数中使用非阻塞动画来为顺序动画生成看起来清晰的代码。
    • 你错了。 setTimeout 不会在不同的线程上执行回调;它等待 UI 线程空闲,然后调用 UI 线程上的回调。因此,Javascript 开发人员不需要处理线程安全开发的所有复杂问题。
    • 请测试我的答案解决方案
    【解决方案2】:

    我认为你应该看看 jQuery queue() 方法。

    queue() 的文档不仅解释了 jQuery 动画并不会真正阻塞 UI,而且实际上是一个接一个地排队。

    它还提供了一种使您的动画和函数调用顺序的方法(这是我对“同步”含义的最佳理解),例如:

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

    这对于异步处理来说当然是多余的;但如果您的方法实际上是一个普通的旧同步 javascript 方法,那可能就是这样做的方法。

    希望这会有所帮助,并为我糟糕的英语感到抱歉......

    【讨论】:

    • 同步意味着fwrite(big_data)fwrite写完之后返回。异步意味着fwrite 将立即返回,并且写入大数据是并行/其他时间完成的。
    • 那么我想我做对了:如果您希望 $("#myThrobber") 的动画在 fwrite(big_data) 之后同步执行,您可以使用以下两个语句来实现: (1) $("#myThrobber").queue(fwrite(big_data)).animate(//whatever); AND (2) 以 $("#myThrobber").dequeue(); 结束 fwrite() 方法注意:我的示例在调用 $(this).dequeue(); 时出错了。它应该是: $("#myThrobber").dequeue();忘记了这一点,因为我从需要的代码中创建了该示例 .queue( jQuery.proxy(myNotAnimatedMethod,this) ) 很抱歉造成这种混乱。
    【解决方案3】:

    jQuery 为其 .animate() 方法提供了一个“步骤”回调。你可以挂钩到这个做同步动画:

    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...
      }
    }
    

    【讨论】:

    • 步骤回调与问题无关。完整的回调正是其他答案所说的。
    • 他试图在另一个动画完成后执行一个动画。他并不想同时为两个元素设置动画。
    • 抱歉——我的大脑在没有的地方插入了一个“a”!
    • 可能不是 OP 所要求的,但这是我需要的 - 谢谢!
    【解决方案4】:

    我同意@SLaks 的观点。您应该为给定的动画使用 jQuery 的回调来创建您的同步动画。您基本上可以将当前动画中的所有内容进行拆分,如下所示:

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

    【讨论】:

    • 你可能明白当它扩展到 20 个动作时会是什么样子......另请参阅我对@SLaks 的回复。
    • 如果你不喜欢它的外观,尽量不要缩进回调(或者只是缩进一点点)。这是唯一的方法。
    【解决方案5】:

    这是我不久前整理的一个模块,用于帮助按顺序运行动画。

    用法:

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

    【讨论】:

      【解决方案6】:

      jQuery 可以制作同步动画。看看这个:

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

      【讨论】:

      • 那是顺序的,不是同步的
      【解决方案7】:

      我遇到了这个http://lab.gracecode.com/motion/ 非常易于使用,并且与 jquery 结合使用效果很好。

      编辑 链接似乎死了。如果我正确地追踪了那些回溯档案,代码在https://github.com/feelinglucky/motion

      【讨论】:

      • 我希望它有英文文档。无论如何,谢谢。
      • @Elazar:你可以让谷歌翻译它;让它有点可以理解;)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-21
      • 1970-01-01
      • 1970-01-01
      • 2016-12-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多