尝试播放声音在keydown与咆哮- AudioContext不允许启动错误



我试图建立一个鼓板应用程序,它主要完成,除了一个问题,我面临的keydown。我设置了当你按下特定的键时,会显示特定的文本并播放特定的声音。这在鼠标点击时非常有效,但是当我尝试使用键盘按钮时,它只显示文本,并给出以下错误:

AudioContext不允许启动。它必须在用户在页面上做手势后恢复(或创建)。@howler.js: 2500

我正在使用useSound钩子,它有Howler作为一个依赖,可能有一个问题,但我不确定。这里是文档的链接:https://github.com/joshwcomeau/use-sound

下面是codesandbox的构建:https://codesandbox.io/s/drum-pad-jc9b5?file=/src/drumPad.css

完整代码:

useEffect(() =>{document.addEventListener("keydown", key)}, []
)
function key(e) {
// This runs the playThis() function when the desired keys are pressed, but the sound doesn't play. 
let i = 0  
let keycodes = drumBank.map(function(y, x){
if (y.keyTrigger === e.key) {
i = x
playThis(i)

}})
} 
const [powerOn, setPowerOn] = useState(true)
const [text, setText] = useState("");
const [Sound0] = useSound(drumBank[0].url) 
const [Sound1] = useSound(drumBank[1].url) 
const [Sound2] = useSound(drumBank[2].url) 
const [Sound3] = useSound(drumBank[3].url) 
const [Sound4] = useSound(drumBank[4].url) 
const [Sound5] = useSound(drumBank[5].url) 
const [Sound6] = useSound(drumBank[6].url) 
const [Sound7] = useSound(drumBank[7].url) 
const [Sound8] = useSound(drumBank[8].url)



function playThis(num) {
if (powerOn === true) 
{ setText(drumBank[num].id)
switch(num) {
case 0: Sound0()
break;
case 1: Sound1()
break;
case 2: Sound2()
break;
case 3: Sound3()
break;
case 4: Sound4()
break;
case 5: Sound5()
break;
case 6: Sound6()
break;
case 7: Sound7()
break;
case 8: Sound8()
break;
}
}
else {setText("Power is off")}
} 


return (
<div id="drum-machine" className="drumpad-container" >
<h3 id={powerOn ? "drum-power-text-on" : "drum-power-text-off"}>Power: </h3>
<div id="drum-power-div" onClick={() => setPowerOn(!powerOn)}>
<div id={powerOn ? "drum-power-button-on" : "drum-power-button-off"}>
</div>
</div>
<div id="display" className="drumpad-display">
<p className="drumpad-text">{text}</p>
</div>
<button className="drum-pad" id="drum-pad-1" onClick={() => playThis(0)} >Q</button>
<button className="drum-pad" id="drum-pad-2" onClick={() => playThis(1)}>W</button>
<button className="drum-pad" id="drum-pad-3" onClick={() => playThis(2)}>E</button>
<button className="drum-pad" id="drum-pad-4" onClick={() => playThis(3)}>A</button>
<button className="drum-pad" id="drum-pad-5" onClick={() => playThis(4)}>S</button>
<button className="drum-pad" id="drum-pad-6" onClick={() => playThis(5)}>D</button>
<button className="drum-pad" id="drum-pad-7" onClick={() => playThis(6)}>Z</button>
<button className="drum-pad" id="drum-pad-8" onClick={() => playThis(7)}>X</button>
<button className="drum-pad" id="drum-pad-9" onClick={() => playThis(8)}>C</button>
</div>
)

}

键函数以某种方式绕过我的功率函数以及显示文本,即使playThis()应该在电源关闭时停用。

如果有人能帮我弄清楚如何在键盘上播放声音,我会很感激的。

我明白了。如果useSound钩子被放入一个函数中,它会在按下键时正常播放声音,然后调用该函数而不是钩子本身。所以,我们不把这些放到playThis():

const [Sound0] = useSound(drumBank[0].url) 
const [Sound1] = useSound(drumBank[1].url) 
const [Sound2] = useSound(drumBank[2].url) 
const [Sound3] = useSound(drumBank[3].url) 
const [Sound4] = useSound(drumBank[4].url) 
const [Sound5] = useSound(drumBank[5].url) 
const [Sound6] = useSound(drumBank[6].url) 
const [Sound7] = useSound(drumBank[7].url) 
const [Sound8] = useSound(drumBank[8].url)

我将这些const放入它们各自的函数中,像这样:

const [Sound0] = useSound(drumBank[0].url) 

const [Sound1] = useSound(drumBank[1].url) 
const [Sound2] = useSound(drumBank[2].url) 
const [Sound3] = useSound(drumBank[3].url) 
const [Sound4] = useSound(drumBank[4].url) 
const [Sound5] = useSound(drumBank[5].url) 
const [Sound6] = useSound(drumBank[6].url) 
const [Sound7] = useSound(drumBank[7].url) 
const [Sound8] = useSound(drumBank[8].url)
let audio0 = () => {sound0()}
let audio1 = () => {sound1()}
let audio2 = () => {sound2()}
let audio3 = () => {sound3()}
let audio4 = () => {sound4()}
let audio5 = () => {sound5()}
let audio6 = () => {sound6()}
let audio7 = () => {sound7()}
let audio8 = () => {sound8()}

,然后在我的playThis()函数我把audio0()而不是sound0(),然后它的工作。这样的:

function playThis(num) {
if (powerOn === true) 
{ setText(drumBank[num].id)
switch(num) {
case 0: audio0()
break;
case 1: audio1()
break;
case 2: audio2()
break;
case 3: audio3()
break;
case 4: audio4()
break;
case 5: audio5()
break;
case 6: audio6()
break;
case 7: audio7()
break;
case 8: audio8()
break;
}
}
else {setText("Power is off")}
} 

至于按键绕过电源按钮,我只是使用了一个useKeyPress插件,这个插件工作得很好。

最新更新