Verified Commit f06295a5 authored by Agate's avatar Agate 💬

Fix #586: The progress bar in the player now display loading state / buffer loading

parent c3fece42
The progress bar in the player now display loading state / buffer loading (#586)
...@@ -51,7 +51,11 @@ ...@@ -51,7 +51,11 @@
<p class="timer total">{{durationFormatted}}</p> <p class="timer total">{{durationFormatted}}</p>
</div> </div>
</div> </div>
<div ref="progress" class="ui small orange inverted progress" @click="touchProgress"> <div
ref="progress"
:class="['ui', 'small', 'orange', 'inverted', {'indicating': isLoadingAudio}, 'progress']"
@click="touchProgress">
<div class="buffer bar" :data-percent="bufferProgress" :style="{ 'width': bufferProgress + '%' }"></div>
<div class="bar" :data-percent="progress" :style="{ 'width': progress + '%' }"></div> <div class="bar" :data-percent="progress" :style="{ 'width': progress + '%' }"></div>
</div> </div>
</div> </div>
...@@ -301,9 +305,11 @@ export default { ...@@ -301,9 +305,11 @@ export default {
...mapState({ ...mapState({
currentIndex: state => state.queue.currentIndex, currentIndex: state => state.queue.currentIndex,
playing: state => state.player.playing, playing: state => state.player.playing,
isLoadingAudio: state => state.player.isLoadingAudio,
volume: state => state.player.volume, volume: state => state.player.volume,
looping: state => state.player.looping, looping: state => state.player.looping,
duration: state => state.player.duration, duration: state => state.player.duration,
bufferProgress: state => state.player.bufferProgress,
queue: state => state.queue queue: state => state.queue
}), }),
...mapGetters({ ...mapGetters({
...@@ -522,4 +528,43 @@ export default { ...@@ -522,4 +528,43 @@ export default {
margin: 0; margin: 0;
} }
@keyframes MOVE-BG {
from {
transform: translateX(0px);
}
to {
transform: translateX(46px);
}
}
.indicating.progress {
overflow: hidden;
}
.ui.progress .bar {
transition: none;
}
.ui.inverted.progress .buffer.bar {
position: absolute;
background-color:rgba(255, 255, 255, 0.15);
}
.indicating.progress .bar {
left: -46px;
width: 200% !important;
color: grey;
background: repeating-linear-gradient(
-55deg,
grey 1px,
grey 10px,
transparent 10px,
transparent 20px,
) !important;
animation-name: MOVE-BG;
animation-duration: 2s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
</style> </style>
...@@ -44,11 +44,17 @@ export default { ...@@ -44,11 +44,17 @@ export default {
} }
}, },
onload: function () { onload: function () {
self.$store.commit('player/isLoadingAudio', false)
self.$store.commit('player/resetErrorCount') self.$store.commit('player/resetErrorCount')
self.$store.commit('player/duration', self.sound.duration()) self.$store.commit('player/duration', self.sound.duration())
let node = self.sound._sounds[0]._node;
node.addEventListener('progress', () => {
self.updateBuffer(node)
})
} }
}) })
if (this.autoplay) { if (this.autoplay) {
self.$store.commit('player/isLoadingAudio', true)
this.sound.play() this.sound.play()
this.$store.commit('player/playing', true) this.$store.commit('player/playing', true)
this.observeProgress(true) this.observeProgress(true)
...@@ -91,10 +97,40 @@ export default { ...@@ -91,10 +97,40 @@ export default {
} }
}, },
methods: { methods: {
updateBuffer (node) {
// from https://github.com/goldfire/howler.js/issues/752#issuecomment-372083163
let range = 0;
let bf = node.buffered;
let time = node.currentTime;
try {
while(!(bf.start(range) <= time && time <= bf.end(range))) {
range += 1;
}
} catch (IndexSizeError) {
return
}
let loadPercentage
let start = bf.start(range)
let end = bf.end(range)
if (range === 0) {
// easy case, no user-seek
let loadStartPercentage = start / node.duration;
let loadEndPercentage = end / node.duration;
loadPercentage = loadEndPercentage - loadStartPercentage;
} else {
let loaded = end - start
let remainingToLoad = node.duration - start
// user seeked a specific position in the audio, our progress must be
// computed based on the remaining portion of the track
loadPercentage = loaded / remainingToLoad;
}
this.$store.commit('player/bufferProgress', loadPercentage * 100)
},
updateProgress: function () { updateProgress: function () {
this.isUpdatingTime = true this.isUpdatingTime = true
if (this.sound && this.sound.state() === 'loaded') { if (this.sound && this.sound.state() === 'loaded') {
this.$store.dispatch('player/updateProgress', this.sound.seek()) this.$store.dispatch('player/updateProgress', this.sound.seek())
this.updateBuffer(this.sound._sounds[0]._node)
} }
}, },
observeProgress: function (enable) { observeProgress: function (enable) {
......
...@@ -8,11 +8,13 @@ export default { ...@@ -8,11 +8,13 @@ export default {
maxConsecutiveErrors: 5, maxConsecutiveErrors: 5,
errorCount: 0, errorCount: 0,
playing: false, playing: false,
isLoadingAudio: false,
volume: 0.5, volume: 0.5,
tempVolume: 0.5, tempVolume: 0.5,
duration: 0, duration: 0,
currentTime: 0, currentTime: 0,
errored: false, errored: false,
bufferProgress: 0,
looping: 0 // 0 -> no, 1 -> on track, 2 -> on queue looping: 0 // 0 -> no, 1 -> on track, 2 -> on queue
}, },
mutations: { mutations: {
...@@ -59,12 +61,18 @@ export default { ...@@ -59,12 +61,18 @@ export default {
playing (state, value) { playing (state, value) {
state.playing = value state.playing = value
}, },
bufferProgress (state, value) {
state.bufferProgress = value
},
toggleLooping (state) { toggleLooping (state) {
if (state.looping > 1) { if (state.looping > 1) {
state.looping = 0 state.looping = 0
} else { } else {
state.looping += 1 state.looping += 1
} }
},
isLoadingAudio (state, value) {
state.isLoadingAudio = value
} }
}, },
getters: { getters: {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment