2011-04-27 33 views
0

我試圖在一個頁面上運行多個動畫(各種各樣的幻燈片),但代碼只針對的一個工作(對我來說)3張幻燈片實際存在。jQuery的:問題分配setIntervals到一個數組

的HTML:

<div class="someclass1" rel="slideshow" type="fade" duration=8500> 
    <div class="wrapper">...</div> 
    <div class="wrapper">...</div> 
</div> 
<div class="someclass2" rel="slideshow" type="slide" duration=4000> 
    <div class="wrapper">...</div> 
    <div class="wrapper">...</div> 
</div> 
<div class="someclass3" rel="slideshow" type="fade" duration=5000> 
    <div class="wrapper">...</div> 
    <div class="wrapper">...</div> 
</div> 

的jQuery:

的問題是不是與動畫,但與實際的初始化和功能的運行(通過看代碼解釋如下更好)

$(function() { 
    var plays = []; 
    var duration = 0; 
    var targets = []; 
    var t = ""; 
    var $obs = $('div[rel="slideshow"]') 
    for(var x = 0; x < $obs.length; x++){ 
     $obs.eq(x).children('.wrapper').eq(0).addClass('active'); 
     $obs.eq(x).children('.wrapper').css({opacity: 0.0}); 
     $obs.eq(x).children('.active').css({opacity: 1.0}); 
     $obs.eq(x).children('.navigation a.slide-buttons').eq(0).addClass('current'); 

     // Set duration 
     duration = $obs.eq(x).attr('duration'); 

     // Set target 
     targets = $obs.eq(x).attr('class').split(' '); 
     t = ''; 
     for(var i=0; i<targets.length; i++){ 
      t += '.' + targets[i]; 
     } 

     if($obs.eq(x).attr('type')==='fade'){ 
      plays[x] = setInterval(function(){fadeSwitch(t);}, duration); 
     } 
     else if($obs.eq(x).attr('type')==='slide'){ 
      plays[x] = setInterval(function(){slideSwitch(t);}, duration); 
     } 
    } 
}); 

通過測試,我已經表明,環成功地運行並通過適當的目標和持續時間要麼fadeSwitch或slideSwitch爲理論值的所有3個運行e循環。

fadeSwitch和slideSwitch是除了動畫部件相同的,例如:

function fadeSwitch(target) { 
var $active = $(target+' .active'); 
if ($active.length === 0){ $active = $(target+' .wrapper:first');} 

var $next = $active.next('.wrapper').length ? $active.next('.wrapper') 
    : $(target+' .wrapper:first'); 

// FADE ANIMATIONS 
$active.animate({opacity : 0.0}, 500, function() { 
    $active.addClass('last-active'); 
}); 
$next.animate({opacity: 1.0}, 500, function() { 
    $active.removeClass('active last-active'); 
    $next.addClass('active'); 
}); 
} 

但是該功能將僅使用最後找到的目標(即T =」 .someClass3' )運行。儘管通過在setInterval函數中放置console.log警報,我知道它正在應用正確的變量。

例如

plays[0] = setInterval(function(){fadeSwitch('.someclass1');}, 8500); 
plays[1] = setInterval(function(){fadeSwitch('.someclass2');}, 4000); 
plays[2] = setInterval(function(){fadeSwitch('.someclass3');}, 5000); 

然而,正如我曾試圖(嚴重)解釋,如果我把一個的console.log fadeSwitch的內部測試的內容被作爲目標通過當它運行(請記住,它設置的時間間隔後運行,所以等到.someClass1函數第一次運行時,plays []數組已滿並且已完成)日誌顯示目標始終是.someClass3,並且它永遠不會成功運行除最後輸入的目標外的其他任何內容。

任何建議或幫助是極大的讚賞。 謝謝。

回答

3

當您撥打setInterval時,t的值正在被您的匿名功能「關閉」。對於你的循環的每一次迭代,你創建一個新的匿名函數,就像你說的那樣,在t有正確的價值。

的問題是,由每個功能執行t的值已改變時(這將保持環的最後一個值),並且所有三個匿名函數指的是相同噸變量(即a的性質封閉和JavaScript的詞彙範圍)。快速的解決辦法是給每個匿名函數正確而不是參照T:

更改此:

plays[x] = setInterval(function(){fadeSwitch(t);}, duration); 

這樣:

plays[x] = setInterval((function(t2){ return function(){ fadeSwitch(t2); }; })(t), duration); 

很顯然同爲與slideSwitch相同。

我覺得我應該指出的另一件事:你在你的html中使用無效的屬性,考慮尋找替代方案,如隱藏的嵌入式標記(例如,<div class="duration" style="display:none">5000</div>)或類名或html5數據屬性,而不是<div duration=5000>

+0

謝謝你的迴應。它完美的作品。 – Houdmont 2011-04-28 13:38:44