Skip to content

Instantly share code, notes, and snippets.

@emmanuelsw
Last active August 5, 2021 03:16
Show Gist options
  • Save emmanuelsw/bf7a64b37e09a342542f40da1d88498f to your computer and use it in GitHub Desktop.
Save emmanuelsw/bf7a64b37e09a342542f40da1d88498f to your computer and use it in GitHub Desktop.
Vue 3 Progress bar component
/* src/main.js */
import { createApp } from 'vue'
import ProgressBar from './components/shared/Progress.vue'
// Global progress bar
const bar = createApp(ProgressBar).mount('#progress-container')
document.body.appendChild(bar.$el)
app.config.globalProperties.$bar = bar
// Add the following div below the <body> tag of the site
// <div id="progress-container"></div>
// If you want to put the progress inside the Vue instance (for example in the layout or below the Navbar)
// you have to validate first that the element exists (#progress-container in this case).
// Now you can use it here
bar.start()
setTimeout(() => {
bar.finish()
}, 2000)
// Or in any view or component
// this.$bar.start()
// this.$bar.finish()
// It can also be combined with navigation guards to automate the progress a little
// https://next.router.vuejs.org/guide/advanced/navigation-guards.html
<!-- src/components/shared/Progress.vue -->
<template>
<div
class="progress"
:style="{
'width': percent+'%',
'height': show ? height : '0px',
'background-color': canSuccess? color : failedColor,
'opacity': show ? 1 : 0
}"
/>
</template>
<script>
export default {
data () {
return {
percent: 0,
show: false,
canSuccess: true,
duration: 3000,
height: '2px',
color: '#008AFF',
failedColor: '#ff0000',
}
},
methods: {
start () {
this.show = true
this.canSuccess = true
if (this._timer) {
clearInterval(this._timer)
this.percent = 0
}
this._cut = 10000 / Math.floor(this.duration)
this._timer = setInterval(() => {
this.increase(this._cut * Math.random())
if (this.percent > 95) {
this.finish()
}
}, 100)
return this
},
set (num) {
this.show = true
this.canSuccess = true
this.percent = Math.floor(num)
return this
},
get () {
return Math.floor(this.percent)
},
increase (num) {
this.percent = this.percent + Math.floor(num)
return this
},
decrease (num) {
this.percent = this.percent - Math.floor(num)
return this
},
finish () {
this.percent = 100
this.hide()
return this
},
pause () {
clearInterval(this._timer)
return this
},
hide () {
clearInterval(this._timer)
this._timer = null
setTimeout(() => {
this.show = false
this.$nextTick(() => {
setTimeout(() => {
this.percent = 0
}, 200)
})
}, 500)
return this
},
fail () {
this.canSuccess = false
return this
},
},
}
</script>
<style scoped>
.progress {
position: fixed;
top: 0px;
left: 0px;
right: 0px;
height: 2px;
width: 0%;
transition: width 0.2s, opacity 0.4s;
opacity: 1;
background-color: #0089FF; /* Change bar color */
z-index: 999999;
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment