涉及jQuery的鼓机排序

时间:2015-06-24 16:09:42

标签: javascript jquery

假设我有以下代码:

  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立即安排未来节拍和我的标记。任何人都知道如何解决这个问题?

1 个答案:

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