I want to implement a music player using Vue and the Vuex Store. I want that the next song starts playing when the current one ends. In normal js, I'd just use:
curr_track.addEventListener("ended", playNext)
where playNext
would be a function I defined inside the same main.js file. When using Vue js and Vuex store, however, I can't do it the same. Any suggestions? I tried to pass the mutations function playNext
inside of my store
, but it did not work. Also, when calling
state.curr_track.duration = track.duration
I get the error:
Uncaught TypeError: Cannot set property duration of #<HTMLMediaElement> which has only a getter
How do I fix this? Thank you
The code is the following:
import { createStore } from 'vuex'
const store = createStore({
state() {
return {
curr_track: null,
track_list: null,
isPlaying: false,
}
},
mutations: {
setTrackList(state, tracks) {
state.track_list = tracks
},
/**
* Load the track and play it
* @param state - the state object
* @param state - the state object
*/
loadTrack(state, track) {
if (state.isPlaying) {
state.curr_track.pause()
}
// get track info
state.curr_track = new Audio()
state.curr_track.id = track.id
state.curr_track.src = track.file
state.curr_track.name = track.name
state.curr_track.artists = track.artists
// TODO: fix duration
// state.curr_track.duration = track.duration
state.curr_track.album_name = track.album.name
state.curr_track.album_cover = track.album.img_cover
state.curr_track.load()
// play track
this.commit('playTrack')
// TODO FIX
state.curr_track.addEventListener("ended", function() {
// if (state.track_list == null) {
// alert('Please select a track first')
// return []
// }
// if (state.track_list[state.track_list.length - 1]['id'] == state.curr_track.id) {
// console.log('last track, go to first')
// this.commit('loadTrack', state.track_list[0])
// } else {
// console.log('go to next track')
// let curr_idx = state.track_list.findIndex(track => track.id == state.curr_track.id)
// this.commit('loadTrack', state.track_list[curr_idx + 1])
// }
})
},
playTrack(state) {
// play loaded track
if (state.curr_track != null) {
state.curr_track.play();
state.isPlaying = true;
} else {
alert('Please select a track first')
}
},
pauseTrack(state) {
// Pause the loaded track
state.curr_track.pause();
state.isPlaying = false;
},
setVolume(state, value) {
// Set the volume
state.curr_track.volume = value
},
/**
* Play the next track: if the current track is the last track in the track list, then load the first track in the
* track list. Otherwise, load the next track in the track list
* @param state - the state object
*/
playNext(state) {
if (state.track_list == null) {
alert('Please select a track first')
return []
}
if (state.track_list[state.track_list.length - 1]['id'] == state.curr_track.id) {
console.log('last track, go to first')
this.commit('loadTrack', state.track_list[0])
} else {
console.log('go to next track')
let curr_idx = state.track_list.findIndex(track => track.id == state.curr_track.id)
this.commit('loadTrack', state.track_list[curr_idx + 1])
}
},
/**
* Play the previous track: if the current track is the first track in the track list, then load the last track in the
* track list. Otherwise, load the previous track in the track list
* @param state - the state object
*/
playPrevious(state) {
if (state.track_list[0]['id'] == state.curr_track.id) {
console.log('first track, got to last one')
this.commit('loadTrack', state.track_list[state.track_list.length - 1])
} else {
console.log('go to previous track')
let curr_idx = state.track_list.findIndex(track => track.id == state.curr_track.id)
this.commit('loadTrack', state.track_list[curr_idx - 1])
}
}
},
getters: {
getIsPlaying(state) {
return state.isPlaying
},
getCurrTrack(state) {
return state.curr_track
}
},
actions: {
}
})
export default store