My work frame: Next.JS v13.4.19
What I am doing: Trying to play soundbites when I press a certain key.
How I am doing it: The function handlePlay() look for certain key press and triggers the play() function for a specific soundbite when it matches.
So far my function works just fine. If I press Q, S or D, it will play the file I want.
My problem: it works only if I click one of the buttons first.
My goal: to play these soundbites from the keyboard as soon as the page has loaded.
My code
"use client"
export default function Home() {
function handlePlay(e) {
if (e.keyCode === 81) {
kick.play()
} else if (e.keyCode === 83) {
hat.play()
} else if (e.keyCode === 68) {
snare.play()
}
};
return (
<div onKeyDown={(e) => handlePlay(e)}>
<audio id="kick" src="kick.wav"></audio>
<audio id="hat" src="hat.wav"></audio>
<audio id="snare" src="snare.wav"></audio>
<button onClick={() => kick.play()}>
Kick
</button>
<button onClick={() => hat.play()}>
Hat
</button>
<button onClick={() => snare.play()}>
Snare
</button>
</div>
)
}
The issue is your div wont capture keyup events unless you're actively pressing keys while the element (Or a child of the element) is focused. Try a useEffect
hook that attaches the listener to the document instead of a specific div:
"use client"
export default function Home() {
useEffect(() => {
document.addEventListener('keydown', handlePlay)
return () => document.removeEventListener('keydown', handlePlay)
}, [])
function handlePlay(e) {
if (e.keyCode === 81) {
kick.play()
} else if (e.keyCode === 83) {
hat.play()
} else if (e.keyCode === 68) {
snare.play()
}
};
return (
<div>
<audio id="kick" src="kick.wav"></audio>
<audio id="hat" src="hat.wav"></audio>
<audio id="snare" src="snare.wav"></audio>
<button onClick={() => kick.play()}>
Kick
</button>
<button onClick={() => hat.play()}>
Hat
</button>
<button onClick={() => snare.play()}>
Snare
</button>
</div>
)
}