VUE.JS Audio Player Bug

Posted In Javascript
  • jamie-bonnett 2 years ago
    Hi All, I'm creating a audio player, but it turns out that two Events are fighting each other. I have an onchange event for a range input which changes the track duration I also have another that updates the players time from the audio current time.
    
    But when I update the track time using the range input it sometimes skips back to where it was.
    
    I also have another bug where the Audio object isn't created before the playlist duration is calculated and displayed, so it appears that the playlist is 00:00 minutes long.
    
    Please bare in mind that the data.audio is first the location of the file and then turned into an Audio object.
    
    Any help would be much appreciated.
    
    Thanks, Jamie
    
    ```
    <body>
      <div id="app" v-model="generateAudioObjects">
        <i class="previous fa fa-fw fa-step-backward" v-on:click="previousTrack"></i>
        <i class="play-pause" v-bind:class="playPauseIcon" v-on:click="ppState"></i>
        <i class="previous fa fa-fw fa-step-forward" v-on:click="nextTrack"></i>
        <span>{{ this.player.currentTime | time }}</span>
        <input type="range" v-bind:value="this.player.currentTime" v-bind:max="currentTrackDuration" v-on:change="changeElapsed($event)" />
        <span>{{ currentTrackDuration | time }}</span>
        <h3>{{ tracks.length }} songs, {{ playlistDuration | time }}</h3>
        <h1 v-for="track in tracksWithPlaying" class="track" v-on:click="gotoTrack(track.id)" v-html="track.title"></h1>
      </div>
    </body>
    
    <script src="js/vue.min.js"></script>
    <script>
      let app = new Vue({
        el: '#app',
        data: {
          tracks: [{
              title: 'Just Be Good To Me (Lee Morrison Mashup)',
              audio: 'sound/Just%20Be%20Good%20To%20Me%20(Lee%20Morrison%20Mashup).mp3'
            },
            {
              title: 'Jess Glynne Vs Katy Perry',
              audio: 'sound/Jess%20Glynne%20Vs%20Katy%20Perry.mp3'
            },
            {
              title: 'Zara Larsson VS KNOXA - Lush Life (Ricardo\'s Weekend Booty)',
              audio: 'sound/Zara%20Larsson%20VS%20KNOXA%20-%20Lush%20Life%20(Ricardo\'s%20Weekend%20Booty).mp3'
            }
          ],
          player: {
            playPauseState: false,
            currentTrackId: 0,
            shuffle: 0,
            repeat: 0,
            volume: 100,
            currentTime: 0,
          }
        },
        filters: {
          time: function(seconds) {
            let h = Math.floor(seconds / 3600);
            let m = Math.floor(seconds % 3600 / 60);
            let s = Math.floor(seconds % 3600 % 60);
    
            let hDisplay = h > 0 ? h + ":" : "";
            let mDisplay = m > 0 ? ("0" + m).slice(-2) + ":" : "00:";
            let sDisplay = s > 0 ? ("0" + s).slice(-2) : "00";
    
            return hDisplay + mDisplay + sDisplay;
          }
        },
        computed: {
          generateAudioObjects: function() {
            for (let i = 0; i < this.tracks.length; i++) {
              if (!(this.tracks[i].audio instanceof Audio)) {
                this.tracks[i].audio = new Audio(this.tracks[i].audio);
                this.tracks[i].id = i;
              }
            }
          },
          playPauseIcon: function() {
            if (!this.player.playPauseState) { // if the button text is play
              return "fa fa-fw fa-play";
            } else {
              return "fa fa-fw fa-pause";
            }
          },
          currentTrack: function() {
            return this.tracks[this.player.currentTrackId];
          },
          currentTrackDuration: function() {
            return this.tracks[this.player.currentTrackId].audio.duration;
          },
          tracksWithPlaying: function() {
            let tempTracks = this.tracks.slice(0);
    
            if (this.player.playPauseState) {
              let id = this.player.currentTrackId;
              tempTracks[id].title += ' <small>Playing</small>';
            }
    
            return tempTracks;
          },
          playlistDuration: {
            cache: false,
            get: function () {
              let duration = 0;
    
              for (let i = 0; i < this.tracks.length; i++) {
                this.tracks[i].audio.readyState > 0 ? duration += this.tracks[i].audio.duration : 0;
              }
    
              return duration;
            }
          }
        },
        methods: {
          ppState: function() {
            if (!this.player.playPauseState) { // if the button text is play
              this.play(); // play the current track
            } else {
              this.pause(); // pause the current track
            }
          },
          play: function() {
            this.player.playPauseState = true; // change the button text to pause
            this.currentTrack.audio.play(); // play the audio track
    
            this.currentTrack.audio.ontimeupdate = function () { // set the audio time listener
              if (this.changeCurrentTime) {
                 this.currentTrack.audio.currentTime = this.player.currentTime;
                 this.changeCurrentTime = false;
              } else {
                this.player.currentTime = this.currentTrack.audio.currentTime; // update player time
              }
    
              if (this.currentTrack.audio.currentTime >= this.currentTrack.audio.duration) { // check if the track has ended
                this.nextTrack(); // go to the next track
              }
            }.bind(this);
          },
          pause: function() {
            this.player.playPauseState = false; // change the button text to play
            this.currentTrack.audio.pause(); // pause the audio track
          },
          nextTrack: function() {
            let id = this.player.currentTrackId; // save the track id to a temproary variable
    
            if (++id >= this.tracks.length) { // check if the end of the tracklist
              id = 0; // start at the beginning of the tracklist
            }
    
            this.gotoTrack(id); // goto the next track
          },
          previousTrack: function() {
            let id = this.player.currentTrackId; // save the track id to a temproary variable
    
            if (--id < 0) { // check if the begginning of the tracklist
              id = this.tracks.length - 1; // start at the end of the tracklist
            }
    
            this.gotoTrack(id); // goto the previous track
          },
          changeElapsed: function(event) {
            this.changeCurrentTime = true;
            this.player.currentTime = event.target.value;
          },
          gotoTrack: function(id) {
            let state = this.player.playPauseState; // get the player current play state
            if (state) this.pause(); // if the player is playing the old track pause it
            this.player.currentTime = this.currentTrack.audio.currentTime = 0; // clear the old track playtime
    
            this.player.currentTrackId = id; // set the player to the new id
    
            if (state) this.play(); // if the player was playing the old track play the new one
          }
        }
      });
    </script>
    ```

    Hi All, I'm creating a audio player, but it turns out that two Events are fighting each other. I have an onchange event for a range input which changes the track duration I also have another that updates the players time from the audio current time.

    But when I update the track time using the range input it sometimes skips back to where it was.

    I also have another bug where the Audio object isn't created before the playlist duration is calculated and displayed, so it appears that the playlist is 00:00 minutes long.

    Please bare in mind that the data.audio is first the location of the file and then turned into an Audio object.

    Any help would be much appreciated.

    Thanks, Jamie

    <body>
      <div id="app" v-model="generateAudioObjects">
        <i class="previous fa fa-fw fa-step-backward" v-on:click="previousTrack"></i>
        <i class="play-pause" v-bind:class="playPauseIcon" v-on:click="ppState"></i>
        <i class="previous fa fa-fw fa-step-forward" v-on:click="nextTrack"></i>
        <span>{{ this.player.currentTime | time }}</span>
        <input type="range" v-bind:value="this.player.currentTime" v-bind:max="currentTrackDuration" v-on:change="changeElapsed($event)" />
        <span>{{ currentTrackDuration | time }}</span>
        <h3>{{ tracks.length }} songs, {{ playlistDuration | time }}</h3>
        <h1 v-for="track in tracksWithPlaying" class="track" v-on:click="gotoTrack(track.id)" v-html="track.title"></h1>
      </div>
    </body>
    
    <script src="js/vue.min.js"></script>
    <script>
      let app = new Vue({
        el: '#app',
        data: {
          tracks: [{
              title: 'Just Be Good To Me (Lee Morrison Mashup)',
              audio: 'sound/Just%20Be%20Good%20To%20Me%20(Lee%20Morrison%20Mashup).mp3'
            },
            {
              title: 'Jess Glynne Vs Katy Perry',
              audio: 'sound/Jess%20Glynne%20Vs%20Katy%20Perry.mp3'
            },
            {
              title: 'Zara Larsson VS KNOXA - Lush Life (Ricardo\'s Weekend Booty)',
              audio: 'sound/Zara%20Larsson%20VS%20KNOXA%20-%20Lush%20Life%20(Ricardo\'s%20Weekend%20Booty).mp3'
            }
          ],
          player: {
            playPauseState: false,
            currentTrackId: 0,
            shuffle: 0,
            repeat: 0,
            volume: 100,
            currentTime: 0,
          }
        },
        filters: {
          time: function(seconds) {
            let h = Math.floor(seconds / 3600);
            let m = Math.floor(seconds % 3600 / 60);
            let s = Math.floor(seconds % 3600 % 60);
    
            let hDisplay = h > 0 ? h + ":" : "";
            let mDisplay = m > 0 ? ("0" + m).slice(-2) + ":" : "00:";
            let sDisplay = s > 0 ? ("0" + s).slice(-2) : "00";
    
            return hDisplay + mDisplay + sDisplay;
          }
        },
        computed: {
          generateAudioObjects: function() {
            for (let i = 0; i < this.tracks.length; i++) {
              if (!(this.tracks[i].audio instanceof Audio)) {
                this.tracks[i].audio = new Audio(this.tracks[i].audio);
                this.tracks[i].id = i;
              }
            }
          },
          playPauseIcon: function() {
            if (!this.player.playPauseState) { // if the button text is play
              return "fa fa-fw fa-play";
            } else {
              return "fa fa-fw fa-pause";
            }
          },
          currentTrack: function() {
            return this.tracks[this.player.currentTrackId];
          },
          currentTrackDuration: function() {
            return this.tracks[this.player.currentTrackId].audio.duration;
          },
          tracksWithPlaying: function() {
            let tempTracks = this.tracks.slice(0);
    
            if (this.player.playPauseState) {
              let id = this.player.currentTrackId;
              tempTracks[id].title += ' <small>Playing</small>';
            }
    
            return tempTracks;
          },
          playlistDuration: {
            cache: false,
            get: function () {
              let duration = 0;
    
              for (let i = 0; i < this.tracks.length; i++) {
                this.tracks[i].audio.readyState > 0 ? duration += this.tracks[i].audio.duration : 0;
              }
    
              return duration;
            }
          }
        },
        methods: {
          ppState: function() {
            if (!this.player.playPauseState) { // if the button text is play
              this.play(); // play the current track
            } else {
              this.pause(); // pause the current track
            }
          },
          play: function() {
            this.player.playPauseState = true; // change the button text to pause
            this.currentTrack.audio.play(); // play the audio track
    
            this.currentTrack.audio.ontimeupdate = function () { // set the audio time listener
              if (this.changeCurrentTime) {
                 this.currentTrack.audio.currentTime = this.player.currentTime;
                 this.changeCurrentTime = false;
              } else {
                this.player.currentTime = this.currentTrack.audio.currentTime; // update player time
              }
    
              if (this.currentTrack.audio.currentTime >= this.currentTrack.audio.duration) { // check if the track has ended
                this.nextTrack(); // go to the next track
              }
            }.bind(this);
          },
          pause: function() {
            this.player.playPauseState = false; // change the button text to play
            this.currentTrack.audio.pause(); // pause the audio track
          },
          nextTrack: function() {
            let id = this.player.currentTrackId; // save the track id to a temproary variable
    
            if (++id >= this.tracks.length) { // check if the end of the tracklist
              id = 0; // start at the beginning of the tracklist
            }
    
            this.gotoTrack(id); // goto the next track
          },
          previousTrack: function() {
            let id = this.player.currentTrackId; // save the track id to a temproary variable
    
            if (--id < 0) { // check if the begginning of the tracklist
              id = this.tracks.length - 1; // start at the end of the tracklist
            }
    
            this.gotoTrack(id); // goto the previous track
          },
          changeElapsed: function(event) {
            this.changeCurrentTime = true;
            this.player.currentTime = event.target.value;
          },
          gotoTrack: function(id) {
            let state = this.player.playPauseState; // get the player current play state
            if (state) this.pause(); // if the player is playing the old track pause it
            this.player.currentTime = this.currentTrack.audio.currentTime = 0; // clear the old track playtime
    
            this.player.currentTrackId = id; // set the player to the new id
    
            if (state) this.play(); // if the player was playing the old track play the new one
          }
        }
      });
    </script>
    
  • vivien-collins 2 weeks ago
    Discussion of the javascript is held and curious for the learns of the fields. It is captivated for the full use of the [https://aussiessayservices.com/australianwritings-com-review/](https://aussiessayservices.com/australianwritings-com-review/) for all vital paths for the terrific outlook and all chips for the manners for the citizens. It’s connected with the realm of the rounded approach for the vicinity for the support for the students.)

    Discussion of the javascript is held and curious for the learns of the fields. It is captivated for the full use of the https://aussiessayservices.com/australianwritings-com-review/ for all vital paths for the terrific outlook and all chips for the manners for the citizens. It’s connected with the realm of the rounded approach for the vicinity for the support for the students.)

Please login or signup to leave a response.

Login

or Sign Up

Sign Up

or Login
×
Want to create your own SAAS?

I can teach you to create your own Software as a Service. Click here to learn more!

Visit SAAS Adventure!