简体   繁体   English

快速触摸时跳过音频 IOS

[英]Audio being skipped during fast ontouch IOS

I have created a flip tile memory game.我创建了一个翻转图块 memory 游戏。 A sequence of tiles will flip over displaying a colour.一系列瓷砖将翻转显示颜色。 The user must remember the sequence and repeat it.用户必须记住顺序并重复。 When the user selects correctly a correct Mp 3 is played.当用户选择正确时,将播放正确的 Mp 3。 On the Iphone if the tiles are selected quickly the audio isn't being played for each touch, its as though the audio is being skipped for some.在 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 ie 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>

It is very hard to tell where your bug comes from, so your solution may not be so easy to find.很难说出你的错误来自哪里,所以你的解决方案可能不那么容易找到。 Some research might tell you some things but otherwise there is an alternative you could try.一些研究可能会告诉您一些事情,但除此之外,您可以尝试其他选择。

The Web Audio API is an interface where you can get more control over the audio you play. Web 音频 API 是一个界面,您可以在其中更好地控制播放的音频。 So in your case instead of manipulating the <audio> element, use the Web Audio API to play your audio files.因此,在您的情况下,不要操纵<audio>元素,而是使用 Web Audio API 来播放您的音频文件。

Down here I've created a snippet which utilizes this API. It currently selects all of your <audio> elements and extracts the sound into a node which then can use to play the sound.在这里,我创建了一个利用这个 API 的片段。它当前选择所有<audio>元素并将声音提取到一个节点中,然后可以使用该节点播放声音。 This gives you control over how the sound plays.这使您可以控制声音的播放方式。

So here it creates an object, which is stored in the sounds constant, that holds all the names as keys and the players as values.所以在这里它创建了一个 object,它存储在sounds常量中,它将所有名称作为键,将玩家作为值。 Something like this:是这样的:

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

Each of those MediaElementAudioSourceNode are the sounds which can be played.这些MediaElementAudioSourceNode中的每一个都是可以播放的声音。 Later in the script there is a playSound function, which plays one of the sounds found in your sounds object.稍后在脚本中有一个playSound function,它播放在您的sounds object 中找到的声音之一。

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');

So all of this could be added above your original script so that the sound files are loaded and ready for use.所以所有这些都可以添加到您的原始脚本之上,以便加载声音文件并准备好使用。 And then use the playSound() function anywhere in your script whenever you want to play anyone of the sounds.然后,只要您想播放任何声音,就可以在脚本的任何位置使用playSound() function。 Example below:示例如下:

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');
        }
      }
    }
  }
}

Also, add a data-name attribute to each <audio> element so that JavaScript knows how to call each player and it's accompanying sound.此外,向每个<audio>元素添加一个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>

All my code above is untested and might throw an error, or worse, makes no difference at all.我上面的所有代码都未经测试,可能会引发错误,或者更糟的是,根本没有任何区别。 But hey, at least it's worth a shot.但是,嘿,至少值得一试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM