2009-10-20 114 views
19

在許多情況下,我希望動畫可以同步執行。特別是當我想要製作一系列連續動畫時。JQuery同步動畫

有沒有簡單的方法來使jQuery animate函數調用同步?

我想過的唯一方法是在動畫完成時將標誌設置爲true並等待此標誌。

回答

24

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

這就是所謂的閉包。

+0

我認爲你可以從setTimeout的UI線程逸出,使我可以肯定地使用非阻塞動畫中的setTimeout功能有連續動畫一個理智的看代碼。 – 2009-10-20 20:11:29

+8

你錯了。 'setTimeout'不在不同的線程上執行回調;它等待UI線程變爲空閒,然後調用UI線程上的回調。因此,Javascript開發人員不需要處理所有線程安全開發的複雜問題。 – SLaks 2009-10-20 20:38:26

+0

測試我的答案解決方案,請 – CuSS 2010-08-25 16:19:06

1

我同意@SLaks對這一個。您應該使用jQuery的回調來創建您的同步動畫。你基本上可以採取任何你有你的當前動畫和分裂它就像這樣:

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

你可能會理解它如何擴展到20個動作時的外觀......也請參閱我對@SLaks的迴應。 – 2009-10-20 20:10:38

+0

如果您不喜歡它的外觀,請不要縮進回調(或者只縮進一點)。這是做到這一點的唯一方法。 – SLaks 2009-10-20 21:38:08

2

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

步驟回調與問題無關。完全回調正是其他答案所說的。 – SLaks 2009-12-08 18:06:20

+0

他正試圖在一個動畫完成後執行一個動畫。他並不是試圖一次動畫兩個元素。 – SLaks 2009-12-08 18:08:31

+0

我的歉意 - 我的大腦插入了一個沒有一個的「a」! – shuckster 2009-12-09 00:18:38

6

我想你應該看看jQuery的queue()方法。

隊列()的文檔不僅解釋了jQuery動畫並不真正阻止用戶界面,而是實際上將它們排隊在一起。

它也有辦法提供,讓您的動畫和函數調用順序(這是我最好的,你的意思是「同步」什麼的理解),如:

$("#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方法,那可能是這樣做的。

希望這有助於爲我的英文不好對不起......

+0

同步意味着'fwrite(big_data)'返回AFTER'fwrite'完成寫入。異步意味着'fwrite'會立即返回,並且寫入大數據是在並行/其他時間完成的。 – 2010-04-27 07:00:58

+0

然後我想我說得對:如果你喜歡動畫$(「#myThrobber」),例如在fwrite(big_data)後同步執行,你可以用下面兩條語句來實現: (1)$( 。 「#myThrobber」)隊列(的fwrite(big_data))動畫(//無論); (2)用$(「#myThrobber」)結束你的fwrite()方法。dequeue(); 注意:我的示例在撥打 $(this).dequeue()時出錯了。 它應該是: $(「#myThrobber」)。dequeue(); 忘了,因爲我從代碼所需的代碼創建 .queue(jQuery.proxy(myNotAnimatedMethod,this)) 對不起,這種混淆。 – 2010-04-27 11:34:31

0

我碰到這個http://lab.gracecode.com/motion/ 真的很容易使用和組合使用jQuery的偉大工程。

編輯 鏈接似乎死了。如果我已經正確地追蹤了那些備忘錄檔案,代碼是https://github.com/feelinglucky/motion

+0

我希望它有英文文檔。無論如何,謝謝。 – 2010-08-01 23:05:24

+2

@Elazar:你可以谷歌翻譯它;使它有點可以理解;) – 2011-06-30 13:00:45

0

jQuery可以製作同步動畫。看看這個:

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

您拼寫「功能」和「DoAnimations」錯誤... – 2011-12-22 16:13:36

+1

@ChrisFrancis只需進行更正。 – Mike 2012-05-30 20:12:01

+1

這是順序的,不是同步的 – SLaks 2012-07-12 18:36:26

0

這是一個模塊,我放在一起,以幫助順序運行動畫。

用法:

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