Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

Commit

Permalink
Clear up flow of state between components and audio element
Browse files Browse the repository at this point in the history
  • Loading branch information
dhruvkb committed Aug 17, 2021
1 parent 0976c24 commit f71863e
Showing 1 changed file with 46 additions and 31 deletions.
77 changes: 46 additions & 31 deletions src/components/AudioTrack/AudioTrack.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,21 @@
<div class="waveform-section bg-dark-charcoal-04">
<Waveform
class="h-30 w-full"
:is-ready="isReady"
:current-time="currentTime"
:duration="duration"
:peaks="audio.peaks"
@sought="updateSeekbar"
@seeked="setPosition"
/>
</div>
<div class="info-section flex flex-row items-end">
<PlayPause :is-playing="isPlaying" @toggle="setPlayState" />
<div class="info ml-6">
<div class="info-section flex flex-row">
<PlayPause
class="self-start flex-shrink-0"
:is-playing="isPlaying"
:disabled="!isReady"
@toggle="setPlayerState"
/>
<div class="info ml-6 self-end">
<i18n path="audio-track.title" tag="p">
<template #title>
<strong>{{ audio.title }}</strong>
Expand All @@ -37,6 +43,12 @@
controls
:src="audio.url"
crossorigin="anonymous"
@loadedmetadata="
setIsReady()
updateTime()
"
@play="setIsPlaying(true)"
@pause="setIsPlaying(false)"
/>
<!-- eslint-enable vuejs-accessibility/media-has-caption -->
</div>
Expand Down Expand Up @@ -66,6 +78,8 @@ export default {
player: null, // HTMLAudioElement
currentTime: 0,
duration: 0,
isReady: false,
isPlaying: false,
}),
computed: {
Expand All @@ -75,52 +89,53 @@ export default {
* @returns {string} the duration in a human-friendly format
*/
durationFmt() {
const seconds = (this.audio.duration ?? 0) / 1000 // ms -> s
const seconds = (this.audio.duration ?? 0) / 1e3 // ms -> s
const date = new Date(0)
date.setSeconds(seconds)
return date.toISOString().substr(11, 8).replace(/^00:/, '')
},
},
watch: {
isPlaying(toVal) {
if (!toVal) {
return // no animation when playback is paused
}
// smoothly animate the progressbar on the waveform component
const loop = () => {
this.updateProgressBar()
if (this.isPlaying) {
// still playing, keep looping
window.requestAnimationFrame(loop)
}
}
window.requestAnimationFrame(loop)
},
},
mounted() {
this.player = this.$refs.audio
},
methods: {
updateProgressBar() {
const elapsed = this.player.currentTime
const total = this.player.duration
this.progress = elapsed / total
updateTime() {
this.currentTime = this.player.currentTime
this.duration = this.player.duration
},
syncTime() {
if (this.player) {
this.updateTime()
}
if (this.isPlaying) {
// still playing, keep looping
window.requestAnimationFrame(this.syncTime)
}
},
updateSeekbar(percentage) {
// Subcomponent events
setPosition(percentage) {
if (this.player.duration) {
this.player.currentTime = this.player.duration * percentage
this.updateTime()
}
this.updateProgressBar()
},
setPlayState(isPlaying) {
this.isPlaying = isPlaying
if (this.isPlaying) {
setPlayerState(isPlaying) {
if (isPlaying) {
this.player.play()
window.requestAnimationFrame(this.syncTime)
} else {
this.player.pause()
}
},
// HTMLAudioElement events
setIsReady() {
this.isReady = true
},
setIsPlaying(isPlaying) {
this.isPlaying = isPlaying
},
},
}
</script>

0 comments on commit f71863e

Please sign in to comment.