除非在全局范围内,否则音频.pause()方法不起作用

时间:2019-08-31 03:34:13

标签: javascript

我正在制作一个简单的剪刀石头布游戏。对于每一个结果,都应该播放一个等效的声音(已经完成),不仅如此,而且如果先前的声音仍在播放,那么它应该在当前声音开始之前停止播放,这就是我的问题:我只能做到这一点如果我将包含“新音频”(在本例中为playSound)的任何变量或对象移到全局作用域,则将工作(停止播放先前的声音)。

我尝试了所有可能想到的事情,经过数小时摆弄变量,函数等,最终我终于有了一个对象(playSound)。我不知道该怎么办,为什么不这样做,我真的想解决这个问题而不求助于全球范围。

const determineWinner = (userChoice, computerChoice) => {
  const playSound = {
    winSound: new Audio("sound/kids-shouting-yay-sound-effect.mp3"),
    loseSound: new Audio("sound/aww-sound-effect.mp3"),
    tieSound: new Audio("sound/roblox-death-sound.mp3"),

    stopSound() {
      this.winSound.pause();
      this.winSound.currentTime = 0;
      this.loseSound.pause();
      this.loseSound.currentTime = 0;
      this.tieSound.pause();
      this.tieSound.currentTime = 0;
    },

    playerWin() {
      this.stopSound();
      this.winSound.play();
      return `Player wins! :D`;
    },

    playerLose() {
      this.stopSound();
      this.loseSound.play();
      return `Computer wins! :(`;
    },

    playerTie() {
      this.stopSound();
      this.tieSound.play();
      return `It's a tie! :/`;
    }
  };

  if ((userChoice === computerChoice)) {
    return playSound.playerTie()
  } else if ((userChoice === 'rock')) {
      if ((computerChoice === 'paper')) {
        return playSound.playerLose();
      } else {
        return playSound.playerWin();
      }
  } else if ((userChoice === 'paper')) {
        if ((computerChoice === 'scissors')) {
        return playSound.playerLose();
      } else {
        return playSound.playerWin();
      }
  } else if ((userChoice === 'scissors')) {
      if ((computerChoice === 'rock')) {
        return playSound.playerLose();
      } else {
        return playSound.playerWin();
      }
  }
};

有关代码的更多信息,这是github的仓库: https://github.com/RenanMDP/rock-paper-scissors

2 个答案:

答案 0 :(得分:1)

  

如果先前的声音仍在播放,则应在当前声音开始之前停止

音频可能是一件棘手的事情,以下是一些需要考虑和建议的事情:

  1. 音频是一种异步操作,因此,事件通常是一种更好的管理方式。
  2. Chrome会返回play之类的音频方法作为承诺,因此stop无法同步完成
  3. 如果仅使用一个Audio元素,则一次只能播放一种声音(不需要stopSound
  4. consthoisted,因此仍放在全局范围内,如果要保持全局范围的整洁,请使用iife

(function(){ // iife

// hand choice functions
const rock = document.querySelector("#rock");
rock.onclick = function() {
  let userInput;
  userInput = rock.getAttribute("id");

  const userChoice = userInput;
  const computerChoice = getComputerChoice();

  document.querySelector("#compChoice").textContent = `Computer picked: ${computerChoice}`;
  document.querySelector("#outcome").textContent = `${determineWinner(userChoice, computerChoice)}`;
}

const paper = document.querySelector("#paper");
paper.onclick = function() {
  let userInput;
  userInput = paper.getAttribute("id");

  const userChoice = userInput;
  const computerChoice = getComputerChoice();

  document.querySelector("#compChoice").textContent = `Computer picked: ${computerChoice}`;
  document.querySelector("#outcome").textContent = `${determineWinner(userChoice, computerChoice)}`;
}

const scissors = document.querySelector("#scissors");
scissors.onclick = function() {
  let userInput;
  userInput = scissors.getAttribute("id");

  const userChoice = userInput;
  const computerChoice = getComputerChoice();

  document.querySelector("#compChoice").textContent = `Computer picked: ${computerChoice}`;
  document.querySelector("#outcome").textContent = `${determineWinner(userChoice, computerChoice)}`;
}

// gets the computer choice
const getComputerChoice = () => {
  const compInput = Math.floor(Math.random() * 3);

  switch (compInput) {
    case 0:
      return 'rock';
      break;
    case 1:
      return 'paper';
      break;
    case 2:
      return 'scissors';
      break;
  }
};

// decides the outcome based on user and computer choices
const determineWinner = (userChoice, computerChoice) => {
  const playSound = {
    audio: document.querySelector("audio"),

    winSound: "https://renanmdp.github.io/rock-paper-scissors/sound/kids-shouting-yay-sound-effect.mp3",
    loseSound: "https://renanmdp.github.io/rock-paper-scissors/sound/aww-sound-effect.mp3",
    tieSound: "https://renanmdp.github.io/rock-paper-scissors/sound/roblox-death-sound.mp3",

    playWinSound() {
      this.audio.src = this.winSound;
      this.audio.play();
    },

    playLoseSound() {
      this.audio.src = this.loseSound;
      this.audio.play();
    },

    playTieSound() {
      this.audio.src = this.tieSound;
      this.audio.play();
    }
  };

  if ((userChoice === computerChoice)) {
    playSound.playTieSound();
    return `It's a tie! :/`;
  } else if ((userChoice === 'rock')) {
    if ((computerChoice === 'paper')) {
      playSound.playLoseSound();
      return `Computer wins! :(`;
    } else {
      playSound.playWinSound();
      return `Player wins! :D`;
    }
  } else if ((userChoice === 'paper')) {
    if ((computerChoice === 'scissors')) {
      playSound.playLoseSound();
      return `Computer wins! :(`;
    } else {
      playSound.playWinSound();
      return `Player wins! :D`;
    }
  } else if ((userChoice === 'scissors')) {
    if ((computerChoice === 'rock')) {
      playSound.playLoseSound();
      return `Computer wins! :(`;
    } else {
      playSound.playWinSound();
      return `Player wins! :D`;
    }
  }
};

})();
body {
  font-family: Verdana, sans-serif;
}

h1 {
  text-align: center;
}

#main-card {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-around;
}

img {
  display: block;
  width: 20vw;
  height: auto;
  margin: 0 auto;
  background-color: rgba(81, 156, 156);
}

img:hover {
  cursor: pointer;
  box-shadow: 0px 0px 2px;
}

figcaption {
  text-align: center;
  padding: 10px;
}

#result {
  width: 100%;
  text-align: center;
  padding: 15px;
  /* border: 5px solid black; */
}

#outcome {
  /* background-image: linear-gradient(red, blue);
  background-clip: text;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent; */
  color: maroon;
}
<h1>
  Pick your hand
</h1>
<div id="main-card">
  <figure>
    <figcaption>Rock</figcaption>
    <img id="rock" src="https://renanmdp.github.io/rock-paper-scissors/img/rps-rock.png">
  </figure>
  <figure>
    <figcaption>Paper</figcaption>
    <img id="paper" src="https://renanmdp.github.io/rock-paper-scissors/img/rps-paper.png">
  </figure>
  <figure>
    <figcaption>Scissors</figcaption>
    <img id="scissors" src="https://renanmdp.github.io/rock-paper-scissors/img/rps-scissors.png">
  </figure>
  <div id="result">
    <h3 id="compChoice"></h3>
    <h1 id="outcome"></h1>
  </div>
</div>
<!-- add empty audio element as a single container for all audio -->
<audio preload="none"></audio>

答案 1 :(得分:0)

成为一种声音来源

var currSound = new Audio("...");

然后使用currSound.play()之前,将currSound更改为要播放的音频。

再发表一条评论,尝试避免重复的行..而不是:

if ((computerChoice === 'paper')) {
    playSound.stopSound();
    playSound.playLoseSound();
    return `Computer wins! :(`;
  } else {
    playSound.stopSound();
    playSound.playWinSound();
    return `Player wins! :D`;
  }

这样写东西:

if ((computerChoice === 'paper')) {
    return computerWin();
  } else {
    return playerWin();
  }

function computerWin(){
 playSound.stopSound();
 playSound.playLoseSound();
 return `Computer wins! :(`;
}

我举了一个小例子

好,您需要先停止播放歌曲。

   playerWin() {
     this.currSound.pause();
     this.currSound = new Audio("sound/aww-sound-effect.mp3");
     this.currSound.play();
     return `Player wins! :D`;
   },