I am trying to make a component in Vue3 to manage audio. This component will display a button that when pressed, plays an audio (just a short word) and changes the color (to show it is playing the audio).
Currently I managed to play the audio, but I have some issues that I am not sure how to resolve, which arise because I don't really understand how the Audio object works in javascript:
- The class
.playingis never applied to the element (isPlaying always returns false!) - How can I check the audio gets loaded before playing it? In case the URL is not reachable the
.play()call should not be executed. But I am not surecanplaythroughevent will work for me, since I just want to load the audio once (and only if the user presses the button). - What is the proper way of managing events for
new Audio()? Try catch or I can do something with promises? - How to unmount this component correctly?
this.audio.pause(); this.audio.src = null?
<template>
<button v-on:click="play" :class="{playing: isPlaying}">Audio</button>
</template>
<script>
export default {
name: 'AudioComponent',
data() {
return {
audio: null,
}
},
props: {
url: {type: String, required: true}
},
computed: {
isPlaying(){
if(this.audio !== null){
if(!this.audio.paused && this.audio.duration > 0){
return true;
}
}
return false;
}
},
methods: {
play(){
if(this.audio === null){
this.audio = new Audio(this.url);
}
this.audio.play();
}
}
}
</script>
<style scoped>
.playing {
color: green;
}
</style>
Note that this is a simplification of the code, but should be enough to see the issue. Since I couldn't find many examples using new Audio call I am wondering if I should use the DOM calls directly instead.
Note that I am using the options API but don't mind answers with composition API too.
isPlayingis never defined in your code.