延迟后播放声音

时间:2019-06-11 07:08:44

标签: javascript settimeout

这里需要帮助。因此,我想循环播放一系列声音,以便在延迟1000毫秒后播放。我该如何实现?我试过了,但它同时运行了所有声音:

我要使用Vanilla JS构建的Simon游戏应用程序的链接:https://codesandbox.io/s/simongame-fcc-4thbk

colorArray.forEach(color => {
  setTimeout(() => {
    color.play();
  }, 1000)
});

4 个答案:

答案 0 :(得分:1)

由于您已经在数组上进行迭代,因此可以在每次迭代中使用每个项目的索引。您可以使用它来为每个迭代步骤计算更高的超时。请注意,这可能会导致重叠的声音播放(假设声音的持续时间为1s),因为setTimeout方法仅保证您指定的最小延迟。它不能保证您的代码何时能正确运行。

colorArray.forEach((color, index) => {
  setTimeout(() => {
    color.play();
  }, 1000*++index)
});

答案 1 :(得分:1)

您可以为声音之间的延迟设置一个不断增加的增量,这将使播放声音间隔1000ms:

colorArray.forEach((color, index) => {
  setTimeout(() => {
    color.play();
  }, 1000 * (index + 1))
//           ^^^^^^^^^ delay more for each following element
});

但是,如果每种声音都大于基本延迟,则可能会遇到问题。因此,如果您有一个2秒钟的声音片段,它将播放并播放一半,则下一个片段也会播放。因此,您可能要等待第一个完成 并等待1000ms,然后再播放下一个。如果您使用的是HTMLMediaElement,则可以收听ended event,并在完成时播放下一个:

//set the event listeners
colorArray
  .reduce((lastColor, currentColor) => {
    lastColor.addEventListener("ended", () => {
      setTimeout(() => {
        currentColor.play();
      }, 1000)
    })
    return currentColor;
  });

//run the first playback which will then run the next one
colorArray[0].play()

一个较小的变化是使用.reduceRight向后迭代事件。您可以这样做:

//set the event listeners
colorArray
  .reduceRight((lastColor, currentColor) => {
    currentColor.addEventListener("ended", () => { // <------------
      setTimeout(() => {  //  current and last are swapped here   |
        lastColor.play(); //<--------------------------------------
      }, 1000)
    })
    return currentColor;
  })
  .play(); //run the first playback which will then run the next one

function playAll() {
  let soundsArray = [...document.querySelectorAll("audio")];

  soundsArray.forEach((sound, index) => {
    setTimeout(() => {
      console.log("waiting for 1 second before playing");
      sound.play();
    }, 1000 * (index + 1));
  });
}

document.querySelector("button").addEventListener("click", playAll)
<audio src="http://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/alien_shoot.wav" controls="controls"></audio>
<audio src="http://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/explosion_02.wav" controls="controls"></audio>
<audio src="http://commondatastorage.googleapis.com/codeskulptor-demos/pyman_assets/intromusic.ogg" controls="controls"></audio>
<audio src="http://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/explosion%2001.wav" controls="controls"></audio>
<br/>
<button>Play All</button>

这是两者的区别-使用第一种方法,特别是第三个声音片段将与第四个声音片段重叠,而第二个声音片段则不会重叠:

function playAll() {
  let soundsArray = [...document.querySelectorAll("audio")];

  soundsArray
    .reduceRight((lastSound, currentSound) => {
      currentSound.addEventListener("ended", () => {
        console.log("waiting for 1 second after playing");
        setTimeout(() => {
          lastSound.play();
        }, 1000)
      });
      return currentSound;
    })
    .play()
}
document.querySelector("button").addEventListener("click", playAll)
<audio src="http://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/alien_shoot.wav" controls="controls"></audio>
<audio src="http://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/explosion_02.wav" controls="controls"></audio>
<audio src="http://commondatastorage.googleapis.com/codeskulptor-demos/pyman_assets/intromusic.ogg" controls="controls"></audio>
<audio src="http://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/explosion%2001.wav" controls="controls"></audio>
<br/>
<button>Play All</button>

我使用了here的声音

答案 2 :(得分:0)

var counter = 1;
colorArray.forEach(color => { setTimeout(() => { color.play(); },counter++*1000) });

这会使colorArray中每个元素的延迟增加1000。

答案 3 :(得分:0)

有一些选择。一种是提前安排所有声音。

colorArray.forEach((color, i) => {
  setTimeout(() => {
    color.play();
  }, 1000 * (i + 1))
});

另一种方法是使用setInterval()。从理论上讲,这将导致更一致的时间安排。

let index = 0;

const intervalId = setInterval(() => {
 if (index < colorArray.length)
   colorArray[index++].play();
 else
   clearInterval(intervalId)
}, 1000)

setInterval()以指定的时间间隔调用回调。这是javascript运行时的内置方法,可以按一定的速度执行工作。

注意:javascript标准不保证在这两种方法中的任何一种定时都将是准确的,但是setInterval的性能应更高,因为它仅在运行时调度一次回调。