【问题标题】:Audio being skipped during fast ontouch IOS在快速 ontouch IOS 期间跳过音频
【发布时间】:2020-04-14 11:57:49
【问题描述】:

我创建了一个翻转记忆游戏。一系列瓷砖将翻转显示一种颜色。用户必须记住顺序并重复。当用户正确选择时,播放正确的 Mp 3。在 Iphone 上,如果快速选择磁贴,则每次触摸都不会播放音频,就好像音频被跳过了一些。 link

const elements = {
    gameContainer: $('#game-container'),
    gameMenu: $('#game-menu'),
    audioPlayer: document.querySelector('#player'),
    audioPlayer2: document.querySelector('#player2'),
    audioPlayer3: document.querySelector('#player3'),
    tiles: $('.tile'),
    correctAlert: $('#correct-alert'),
    wrongAlert: $('#wrong-alert'),
    failAlert: $('#fail-alert'),
    alertModal: $('#alert-modal'),
    stageNumber: $('.stage-number'),
    maxStageNumber: $('.max-stage-number'),
    gamemodeCheckbox: $('#gamemode-checkbox'),
    stageProgress: $('#stage-progress'),
    waitText: $('#wait-text'),
    wonAlert: $('#won'),
    goText: $('#go-text')
};

function tileClicked(tile) {
  console.dir(tile)
  // only allow clicking on tiles when game is started and game is not showing pattern
  if (!game.showing && game.started && !tile.classList.contains('flip-card-onclick')) {

    flipTile(tile);

    // check if game reached maximum number of stages i.e. game has been won
    if (game.playerMove <= game.maxStageNumber) {

      // check if current move (tile clicked) matches the tile in the generated pattern
      if (parseInt(tile.id) == game.currentGame[game.playerMove]) {
        // increase the pattern pointer
        game.playerMove++;

        // play sound when correct tile has been clicked
        elements.audioPlayer.pause();
        elements.audioPlayer.currentTime = 0;
        elements.audioPlayer.play();



        // check if we reached the end of the current pattern
        if (game.playerMove == game.currentGame.length) {
          // update the progress bar
          elements.stageProgress.css('width', `${(game.currentGame.length / game.maxStageNumber) * 100}%`);

          // show alert prompting user to go to the next stage
          elements.correctAlert.modal('show');
        }
        // current move did not match current pattern, wrong move
      } else {

        if (game.strictGamemode) {
          elements.audioPlayer2.play();
          // show fail alert and prompt to restart or exit game if strict mode has been selected
          elements.failAlert.modal('show');
        } else {
          // show wrong move alert and prompt to show pattern again
          elements.audioPlayer2.play();
          elements.wrongAlert.modal('show');
        }
      }
    }
  }
}
<!--Audio Player-->
<audio controls id="player" class="d-none">
         <source id="player-src" src="assets/audio/correct.mp3">
      </audio>
<audio controls id="player2" class="d-none">
         <source id="player-src-2" src="assets/audio/incorrect.mp3">
      </audio>
<audio controls id="player3" class="d-none">
         <source id ="player-src-3" src="assets/audio/won.mp3">
	  </audio>

【问题讨论】:

  • 如果无法重现这种情况,就很难判断。你能举出这样一个可重复的例子吗?
  • link@EmielZuurbier 这里有一个链接,指向它在 iphone 上的屏幕录制。我希望每次点击瓷砖都能播放正确的声音。正如视频中所见,我们只听过一次。
  • 好的,将视频链接添加到您的问题中,以便其他人也可以看到。您能否更具体地说明在什么时候预期哪种声音。 JS文件中的其他声音是怎么播放的?
  • @EmielZuurbier 我在帖子中添加了更多的 js 代码。我通过 ID 获取音频播放器。

标签: javascript ios audio-player ontouchstart


【解决方案1】:

很难判断您的错误来自何处,因此您的解决方案可能并不那么容易找到。一些研究可能会告诉您一些事情,但您可以尝试另一种选择。

Web Audio API is 是一个界面,您可以在其中更好地控制您播放的音频。因此,在您的情况下,不要使用 &lt;audio&gt; 元素,而是使用 Web Audio API 来播放您的音频文件。

在这里,我创建了一个使用此 API 的 sn-p。它当前选择所有&lt;audio&gt; 元素并将声音提取到一个节点中,然后可以使用该节点播放声音。这使您可以控制声音的播放方式。

所以它在这里创建了一个对象,该对象存储在sounds 常量中,它将所有名称作为键,将玩家作为值。像这样的:

const sounds {
  'correct': MediaElementAudioSourceNode,
  'incorrect': MediaElementAudioSourceNode,
  'won': MediaElementAudioSourceNode
};

MediaElementAudioSourceNode 中的每一个都是可以播放的声音。稍后在脚本中有一个 playSound 函数,它播放在您的 sounds 对象中找到的声音之一。

const AudioContext = window.AudioContext || window.webkitAudioContext;
const audioContext = new AudioContext();

const audioElements = document.querySelectorAll('audio');

const createAudioSources = audioElements => {
    const audioSources = {};
    for (const audioElement of audioElements) {
        const name = audioElement.dataset.name;
        const track = audioContext.createMediaElementSource(audioElement);
        audioSources[name] = track;
    }
    return audioSources;
};

const sounds = createAudioSources(audioElements);

function playSound(track) {
    const sound = sounds[track];
    if (sound === undefined) return;
    sound.connect(audioContext.destination);
    sound.start(audioContext.currentTime);
};

playSound('correct');
playSound('incorrect');
playSound('won');

因此,所有这些都可以添加到您的原始脚本之上,以便加载声音文件并准备好使用。然后,只要您想播放任何声音,就可以在脚本中的任何位置使用playSound() 函数。示例如下:

function tileClicked(tile) {
  console.dir(tile)
  // only allow clicking on tiles when game is started and game is not showing pattern
  if (!game.showing && game.started && !tile.classList.contains('flip-card-onclick')) {

    flipTile(tile);

    // check if game reached maximum number of stages i.e. game has been won
    if (game.playerMove <= game.maxStageNumber) {

      // check if current move (tile clicked) matches the tile in the generated pattern
      if (parseInt(tile.id) == game.currentGame[game.playerMove]) {
        // increase the pattern pointer
        game.playerMove++;

        // play sound when correct tile has been clicked
        playSound('correct');

        // check if we reached the end of the current pattern
        if (game.playerMove == game.currentGame.length) {
          // update the progress bar
          elements.stageProgress.css('width', `${(game.currentGame.length / game.maxStageNumber) * 100}%`);

          // show alert prompting user to go to the next stage
          elements.correctAlert.modal('show');
        }
        // current move did not match current pattern, wrong move
      } else {

        if (game.strictGamemode) {
          playSound('incorrect');
          // show fail alert and prompt to restart or exit game if strict mode has been selected
          elements.failAlert.modal('show');
        } else {
          // show wrong move alert and prompt to show pattern again
          playSound('incorrect');
          elements.wrongAlert.modal('show');
        }
      }
    }
  }
}

此外,为每个 &lt;audio&gt; 元素添加一个 data-name 属性,以便 JavaScript 知道如何调用每个播放器以及伴随的声音。

<audio controls id="player" class="d-none" data-name="correct">
  <source id="player-src" src="assets/audio/correct.mp3">
</audio>
<audio controls id="player2" class="d-none" data-name="incorrect">
  <source id="player-src-2" src="assets/audio/incorrect.mp3">
</audio>
<audio controls id="player3" class="d-none" data-name="won">
  <source id ="player-src-3" src="assets/audio/won.mp3">
</audio>

我上面的所有代码都未经测试,可能会引发错误,或者更糟糕的是,根本没有任何区别。但是,嘿,至少值得一试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多