2017-06-16 67 views
0

此代碼隨機播放音頻元素。兩次運行setup可以讓你用兩個不同的陣列同時做到這一點,這正是我想要的。問題是#stop只能停止其中一個陣列的播放。這實際上也會發生,如果你只在一個陣列上調用setup,但不止一次點擊#start(我也不想)。我認爲這與'intervalReturn'有關,因爲它只會被指定爲一個setInterval帶一個功能的多setIntervals(Javascript)

我應該如何編寫這個程序,以便多個調用setup創建可以只啓動一次的不同setIntervals?另外,如果我應該從完全不同的角度來看待這個問題,會更好嗎?

編輯:這是根據以下建議修復的。但我想知道,在setInterval的「引擎蓋下」是怎麼回事?爲什麼這種行爲會發生? (具體做法是:#stop停止一個但不是所有的音頻內容。)

var CMajor3 = new Array ("C3","D3","E3","F3","G3","A3","B3","C4a"); 
var CMajor4 = new Array ("C4b","D4","E4","F4","G4","A4","B4","C5"); 

var intervalReturn = null; 

function pickAndPlay(pitchSet){ 
    fyshuffle (pitchSet); // the Fischer-Yates shuffle function 
    var tone = document.getElementById(pitchSet[0]); 
    tone.currentTime = 0; 
    tone.play();  
}; 

function setup(time, pitchSet){ 
    $("#start").click(function() { 
     console.log("startClicked"); 
     intervalReturn = window.setInterval(pickAndPlay, time, pitchSet) 
    }); 
    $("#stop").click(function() { 
     console.log("stopClicked"); 
     window.clearInterval(intervalReturn) 
    }); 
}; 

$(document).ready(function() { 
    setup(2000, CMajor3); 
    setup(2000, CMajor4); 
}); 
+2

問題是單個'intervalReturn'變量不能同時保存兩個不同的值! - 嘗試移動'var intervalReturn = null'作爲'function setup'中的第一行 –

+0

請參閱編輯評論? –

+1

*「這個...也會發生,如果你......點擊#開始多次。」 - 這是你想要做的事嗎?或者,在再次點擊開始之前,用戶是否必須停止前一個? – nnnnnn

回答

1

但我想知道,什麼是要去在使用setInterval這裏的「引擎蓋下」?

每次調用setup()時間,創建於#start#stop元素額外單擊處理。當您實際單擊#start#stop,時,將調用所有適用處理程序的所有(按照它們綁定的相同順序)。這就是爲什麼點擊#start導致CMajor3CMajor4筆記發揮。你會得到多個同時但不相關的間隔運行。

被定義爲一個全局變量intervalReturn,你永遠只能有一個是從最近一次調用返回setInterval()區間ID,因爲每個#start點擊處理程序運行它的時候會覆蓋前一個。這就是爲什麼點擊#stop只能停止其中一個時間間隔,並且無法阻止其他時間。

移動setup()函數內var intervalReturn聲明幫助,因爲這樣closures work in JS是參數和局部變量setup(),即timepitchSetintervalReturn(你感動的聲明之後)在這兩個事件處理程序訪問定義在當前調用setup()。隨後對setup()的調用會使用它們自己的這些變量的單獨副本創建新的關閉。那麼#stop點擊處理程序使用與其自己的setup()相關的個人intervalReturn。由於兩個#stop處理程序都運行,所以兩個時間間隔都會被清除。

但你仍然有點擊超過一次#start#更不點擊#stop這個問題產生了額外的時間間隔,然後內的任何一個setup()個別intervalReturn得到了最新的覆蓋,因此再次#stop沒有辦法指回到先前的間隔。這就是爲什麼在#start處理程序中添加if (intervalReturn === null)有助於在尚未運行的情況下僅啓動新的時間間隔的原因。(然後你需要添加intervalReturn = null#stop處理程序,因爲只調用clearInterval(intervalReturn)不改變intervalReturn變量的值。)

建議:更新現有console.log()語句如下:

console.log("startClicked", pitchSet, intervalReturn); 
// and 
console.log("stopClicked", pitchSet, intervalReturn); 

也許更多的startClicked之一,剛剛打電話setInterval(),以便它記錄剛剛返回的間隔ID,而不是以前的之一。這樣你可以看到所有相關變量的值,看看發生了什麼。

+0

令人驚歎!非常感謝您的詳細解釋。它使我更清楚需要研究什麼來了解這個項目。 –