1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
<script setup>
const props = defineProps({
throttle: {
type: Number,
default: 200
},
duration: {
type: Number,
default: 2000
}
})
const nuxtApp = useNuxtApp()
// Options & Data
const data = reactive({
percent: 0,
show: false,
canSucceed: true
})
// Local variables
let _timer = null
let _throttle = null
let _cut
// Functions
function clear () {
_timer && clearInterval(_timer)
_throttle && clearTimeout(_throttle)
_timer = null
}
function start () {
if (data.show) { return }
clear()
data.percent = 0
data.canSucceed = true
if (props.throttle) {
_throttle = setTimeout(startTimer, props.throttle)
} else {
startTimer()
}
}
function increase (num) {
data.percent = Math.min(100, Math.floor(data.percent + num))
}
function finish () {
data.percent = 100
hide()
}
function hide () {
clear()
setTimeout(() => {
data.show = false
setTimeout(() => {
data.percent = 0
}, 400)
}, 500)
}
function startTimer () {
data.show = true
_cut = 10000 / Math.floor(props.duration)
_timer = setInterval(() => {
increase(_cut)
}, 100)
}
// Hooks
nuxtApp.hook('content:middleware:start', start)
nuxtApp.hook('page:start', start)
nuxtApp.hook('page:finish', finish)
onBeforeUnmount(() => clear)
</script>
<template>
<div
class="nuxt-progress"
:class="{
'nuxt-progress-failed': !data.canSucceed,
}"
:style="{
width: `${data.percent}%`,
left: data.left,
opacity: data.show ? 1 : 0,
backgroundSize: `${(100 / data.percent) * 100}% auto`,
}"
/>
</template>
<style lang="ts">
css({
'.nuxt-progress': {
height: '{docus.loadingBar.height}',
position: 'fixed',
top: '0px',
left: '0px',
right: '0px',
width: '0%',
opacity: 1,
transition: 'width 0.1s, height 0.4s, opacity 0.4s',
background: 'repeating-linear-gradient(to right, {docus.loadingBar.gradientColorStop1} 0%, {docus.loadingBar.gradientColorStop2} 50%, {docus.loadingBar.gradientColorStop3} 100%)',
zIndex: '999999',
}
})
</style>
|