【问题标题】:How to add delay between each iteration in Javascript For loop如何在Javascript For循环中的每次迭代之间添加延迟
【发布时间】:2017-07-22 11:37:40
【问题描述】:

我正在为 FreeCodeCamp 创建一个 Simon 游戏,并尝试使用 for 循环为每个模式播放音频。

我现在的代码一次播放所有音频,这对游戏不起作用。如何更改此代码,以便它单独播放每个音频声音,中间有 0.5 秒的中断?

这是播放音频并添加视觉效果的功能

function playAudio() {
    if (colorColor === "red") {
      red.play();
      $('#red').effect("highlight", { color: colorColor }, 500);
    } else if (colorColor === "blue") {
      blue.play();
      $('#blue').effect("highlight", { color: colorColor }, 500);
    } else if (colorColor === "green") {
      green.play();
      $('#green').effect("highlight", { color: colorColor }, 500);
    } else if (colorColor === "yellow") {
      yellow.play();
      $('#yellow').effect("highlight", { color: colorColor }, 500);
    }
}

这是我认为问题所在的函数。

function playPattern() {
    for (var i = 0; i < pattern.length; i++) {
      colorColor = pattern[i];
      setTimeout(playAudio, 500);
    }
  setTimeout(random, 750);
}

这里的 random() 函数只是因为它是在 playPattern() 中调用的

function random() {
    randomColor = colors[Math.floor(Math.random() * colors.length)];
    colorColor = randomColor;
    colorColor = colorColor.slice(1);
    pattern.push(colorColor);

    count++;
    if (count < 10) {
      document.getElementById("count").innerHTML = "0" + count;
    } else {
      document.getElementById("count").innerHTML = count;
    }

    playAudio();

    pickCount = 0;
    userPick = [];
}

谢谢!

【问题讨论】:

  • 使用setTimeout(playAudio, i * 500);
  • 执行for循环时,所有超时设置为相同的500ms。所以所有的音频都是同时播放的。
  • 我将其更改为该代码,但似乎仍然无法正常工作。
  • 我阅读了该帖子并尝试了答案中的功能,但仍然无法正常工作。

标签: javascript


【解决方案1】:

假设您的音频长度都相同:

var audioLength = 3000; // length of audio in ms

for (var i = 0; i < pattern.length; i++) {
  colorColor = pattern[i];
  setTimeout(playAudio, (i * (audioLength + 500));
}

【讨论】:

    【解决方案2】:

    在您正在执行的代码中:

    for (var i = 0; i < pattern.length; i++) {
      colorColor = pattern[i];
      setTimeout(playAudio, 500);
    }
    

    发生的情况是,您基本上定义为所有模式在 500 毫秒内运行 playAudio。 for 循环立即处理,500 毫秒后所有音频一起播放。

    您想要的是仅在 playAudio 函数结束时调用下一次超时。

    let i = 0;
    function playAudio() {
        i++;
        colorColor = pattern[i];
        if (colorColor === "red") {
          red.play();
          $('#red').effect("highlight", { color: colorColor }, 500);
        } else if (colorColor === "blue") {
          blue.play();
          $('#blue').effect("highlight", { color: colorColor }, 500);
        } else if (colorColor === "green") {
          green.play();
          $('#green').effect("highlight", { color: colorColor }, 500);
        } else if (colorColor === "yellow") {
          yellow.play();
          $('#yellow').effect("highlight", { color: colorColor }, 500);
        }
        if (i < pattern.length) {
            setTimeout(playAudio, 500);
        }
    }
    
    function random() {
        randomColor = colors[Math.floor(Math.random() * colors.length)];
        colorColor = randomColor;
        colorColor = colorColor.slice(1);
        pattern.push(colorColor);
    
        count++;
        if (count < 10) {
          document.getElementById("count").innerHTML = "0" + count;
        } else {
          document.getElementById("count").innerHTML = count;
        }
    
        playAudio();
    
        pickCount = 0;
        userPick = [];
    }
    
    setTimeout(random, 750);
    

    【讨论】:

    • 我并没有完全使用它,但它确实帮助我得到了答案,所以谢谢!
    【解决方案3】:

    我的回答基于this answer

    我所做的是通过创建一个object 来预加载音频文件,其中标题为键,对象值包含文件的源以及是否已加载:

    const notes = ['do', 're', 'mi', 'fa', 'sol', 'la', 'ti'];
    const audioFiles = notes.reduce((obj, title) => {
      obj[title] = {
        src: `notes/${title}.wav`,
        loaded: false,
      };
    
      return obj;
    }, {});
    
    // Preload files.
    Object.entries(audioFiles).forEach(([title, details]) => {
      const audio = new Audio();
    
      audio.addEventListener('canplaythrough', () => {
        details.loaded = true;
      });
    
      audio.src = details.src;
    });
    

    playPlaylist 函数接受一个播放列表(标题数组)和一个包含音频文件的对象:

    const playAudio = function playAudio(player, src) {
      player.src = src;
      player.play();
    };
    
    const playPlaylist = function playPlaylist(playlist, files) {
      // TODO: Check if files in playlist are already loaded.
      // while (!filesLoaded) { ... }
    
      const player = new Audio();
      let audioIndex = 0;
    
      player.addEventListener('ended', () => {
        audioIndex++;
    
        if (audioIndex >= playlist.length) {
          return;
        }
    
        setTimeout(() => {
          playAudio(player, files[playlist[audioIndex]].src);
        }, 500);
      });
    
      playAudio(player, files[playlist[audioIndex]].src);
    };
    

    然后只需提供播放列表并传递 audioFiles 对象。

    // Play sample playlist.
    const playlist = 'do,mi,fa,sol,do,re,la,fa,mi'.split(',');
    playPlaylist(playlist, audioFiles);
    

    只需更改要测试的文件和文件路径。

    【讨论】:

      【解决方案4】:

      您需要考虑歌曲的持续时间,并将其包含在您的超时中,例如,如果红色持续 1 分钟,您需要将下一个超时设置为 setTimeout(blue, 60*1000 + 500),如下所示:

      function playAudio(color) {
          if (colorColor === "red") {
            red.play();
            $('#red').effect("highlight", { color: colorColor }, 500);
            setTimeout(function () {
               playAudio("blue");
            },60*1000 + 500);
          } else if (colorColor === "blue") {
            blue.play();
            $('#blue').effect("highlight", { color: colorColor }, 500);
            setTimeout(function () {
               playAudio("green");
            },60*1000 + 500);
          } else if (colorColor === "green") {
          //.... ETC
      

      你不需要 for,只需要一些递归

      【讨论】:

        猜你喜欢
        • 2015-01-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-11
        • 2017-04-03
        相关资源
        最近更新 更多