Воспроизвести массив звуков после задержки - PullRequest
2 голосов
/ 11 июня 2019

нужна помощь здесь. Итак, я хочу просмотреть массив звуков, чтобы он воспроизводился после задержки, скажем, 1000 мс. Как мне этого добиться? Я попробовал это, но он запускает все звуки одновременно:

Ссылка на игровое приложение Simon, которое я пытаюсь создать с использованием Vanilla JS: https://codesandbox.io/s/simongame-fcc-4thbk

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

Ответы [ 4 ]

1 голос
/ 11 июня 2019

Вы можете установить возрастающее увеличение задержки между звуками, которая будет разносить воспроизведение звуков на расстоянии 1000 мс:

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

Однако вы можете столкнуться с проблемой, есликаждый звук больше базовой задержки.Таким образом, если у вас есть 2-секундный аудиоклип, который будет воспроизводиться и на полпути, будет воспроизводиться и следующий.Таким образом, вы можете подождать, пока первый завершит , а подождать 1000 мс, прежде чем играть следующий.Если вы используете HTMLMediaElement, то вы можете прослушать событие ended , а когда закончите, сыграть следующее:

//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>

Я использовал звуки здесь

1 голос
/ 11 июня 2019

Поскольку вы уже выполняете итерацию по массиву, это делает индекс каждого элемента доступным в каждой итерации. Вы можете использовать это для расчета более высокого времени ожидания для каждого шага итерации. Обратите внимание, что это, вероятно, приведет к перекрытию воспроизведения звука (при условии, что продолжительность звука составляет 1 с), поскольку метод setTimeout гарантирует только минимальную задержку, указанную вами. Это не гарантирует, когда ваш код будет работать точно.

colorArray.forEach((color, index) => {
  setTimeout(() => {
    color.play();
  }, 1000*++index)
});
0 голосов
/ 11 июня 2019

Есть несколько вариантов.Одним из них является планирование всех звуков заранее.

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 должна быть более производительнойпоскольку он только планирует один обратный вызов со временем выполнения.

0 голосов
/ 11 июня 2019
var counter = 1;
colorArray.forEach(color => { setTimeout(() => { color.play(); },counter++*1000) });

Это увеличивает задержку на 1000 для каждого элемента в colorArray.

...