假设我有以下代码:
var blinker = function(element){
if(stopped){
return;
} else {
var sampleMapping = {'0': 'bass.wav',
'1': 'clap(2).wav',
'2': 'hihat(4).wav',
'3': 'tom(9).wav',
'4': 'hihat.wav',
'5': 'ArpEC1.wav'}
if (element.attr('value') === 'hit'){
var sample = element.attr('id');
instrument(sample);
}
element.fadeOut(200);
element.fadeIn(200);
}
}
var sequencerRun = function(){
var currentTime = 0;
var starting = 200;
var startTime = 0;
for(var k = 0; k < 16; k++){
$(".instrument td .beat" + k).each(function(){
setTimeout(blinker, currentTime,$(this));
})
currentTime += starting;
}
}
var timerId, setInt;
var runSeq = function(){
setInt = setInterval(sequencerRun,3200);
}
$('.play').click(function(){
stopped = false
sequencerRun();
runSeq();
})
$('.stop').click(function(){
clearInterval(setInt);
stopped = true;
})
我有编写代码来执行在我的鼓机中运行的音序器。我的应用的部署版本可以看到here
所以我所做的是使用table
HTML结构创建一个矩阵。单击播放时,将调用sequencerRun并运行一次。在第一次运行之后,setInterval会小心调用所有sequencerRun,直到用户单击stop。这些点击事件监听器中有一个标志,我将回来。
此测序的核心是sequencerRun
。对于我的矩阵中的每一列,它对应一个节拍,我正在安排对该列的检查,以查看是否已选择任何元素用于将来播放。 sequencerRun
只负责日程安排。更明确地说:
setTimeout(blinker,0, $(this)) is the same as check the first column right away
setTimeout(blinker,0, $(this)) is the same as check the second column at time 200
setTimeout(blinker,0, $(this)) is the same as check the third column at time 400
....
setTimeout(blinker,0, $(this)) is the same as check the sixteenth column at time 3200
现在blinker
做的是检查是否停止,我创建的原始标志是true还是false。点击停止时会变为真,这意味着没有执行列检查,也没有播放。如果错误则执行鼓机的正常过程。
现在问题出在这里。如果你去了应用程序的部署版本,这个标记引入了一个讨厌的bug。如果您按下播放序列发生器,则会出现该错误,但如果再次单击播放,则会启动另一次运行,这不是鼓机应该如何工作。难以理解的是,如果我按下播放,如果再次按下播放,则不会启动其他音序器运行。此外,如果你点击播放,停止,播放我得到相同的副作用。我认为我的主要问题是sequencerRun
立即安排未来节拍和我的标记。任何人都知道如何解决这个问题?
答案 0 :(得分:1)
只需在stopped
点击处理程序中使用您的.play
变量:
$('.play').click(function(){
if (stopped) {
stopped = false
sequencerRun();
runSeq();
}
});
如果stopped
标志为false,则再次单击“播放”将不执行任何操作。要在单击“停止”时停止其余的排队序列,您需要清除已设置的超时。首先,确保你掌握每一个:
var sequenceTimeouts = [];
var sequencerRun = function(){
var currentTime = 0;
var starting = 200;
var startTime = 0;
//reset array
sequenceTimeouts = [];
for(var k = 0; k < 16; k++){
$(".instrument td .beat" + k).each(function(){
//push each timeout into the array
sequenceTimeouts.push(setTimeout(blinker, currentTime,$(this)));
})
currentTime += starting;
}
}
然后在你的停止点击处理程序中,清除每一个:
$.each(sequenceTimeouts, function(i, timeout) {
clearTimeout(timeout);
});