You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
157 lines
3.4 KiB
157 lines
3.4 KiB
<template>
|
|
<uni-progress
|
|
class="uni-progress"
|
|
v-on="$listeners"
|
|
>
|
|
<div
|
|
:style="outerBarStyle"
|
|
class="uni-progress-bar"
|
|
>
|
|
<div
|
|
:style="innerBarStyle"
|
|
class="uni-progress-inner-bar"
|
|
/>
|
|
</div>
|
|
<template v-if="showInfo">
|
|
<p class="uni-progress-info">
|
|
{{ currentPercent }}%
|
|
</p>
|
|
</template>
|
|
</uni-progress>
|
|
</template>
|
|
<script>
|
|
const VALUES = {
|
|
activeColor: '#007AFF',
|
|
backgroundColor: '#EBEBEB',
|
|
activeMode: 'backwards'
|
|
}
|
|
export default {
|
|
name: 'Progress',
|
|
props: {
|
|
percent: {
|
|
type: [Number, String],
|
|
default: 0,
|
|
validator (value) {
|
|
return !isNaN(parseFloat(value, 10))
|
|
}
|
|
},
|
|
showInfo: {
|
|
type: [Boolean, String],
|
|
default: false
|
|
},
|
|
strokeWidth: {
|
|
type: [Number, String],
|
|
default: 6,
|
|
validator (value) {
|
|
return !isNaN(parseFloat(value, 10))
|
|
}
|
|
},
|
|
color: {
|
|
type: String,
|
|
default: VALUES.activeColor
|
|
},
|
|
activeColor: {
|
|
type: String,
|
|
default: VALUES.activeColor
|
|
},
|
|
backgroundColor: {
|
|
type: String,
|
|
default: VALUES.backgroundColor
|
|
},
|
|
active: {
|
|
type: [Boolean, String],
|
|
default: false
|
|
},
|
|
activeMode: {
|
|
type: String,
|
|
default: VALUES.activeMode
|
|
}
|
|
},
|
|
data () {
|
|
return {
|
|
currentPercent: 0,
|
|
strokeTimer: 0,
|
|
lastPercent: 0
|
|
}
|
|
},
|
|
computed: {
|
|
outerBarStyle () {
|
|
return `background-color: ${this.backgroundColor}; height: ${this.strokeWidth}px;`
|
|
},
|
|
innerBarStyle () {
|
|
// 兼容下不推荐的属性,activeColor 优先级高于 color。
|
|
let backgroundColor = ''
|
|
if (this.color !== VALUES.activeColor && this.activeColor === VALUES.activeColor) {
|
|
backgroundColor = this.color
|
|
} else {
|
|
backgroundColor = this.activeColor
|
|
}
|
|
return `width: ${this.currentPercent}%;background-color: ${backgroundColor}`
|
|
},
|
|
realPercent () {
|
|
// 确保最终计算时使用的是 Number 类型的值,并且在有效范围内。
|
|
let realValue = parseFloat(this.percent, 10)
|
|
realValue < 0 && (realValue = 0)
|
|
realValue > 100 && (realValue = 100)
|
|
return realValue
|
|
}
|
|
},
|
|
watch: {
|
|
realPercent (newValue, oldValue) {
|
|
this.strokeTimer && clearInterval(this.strokeTimer)
|
|
this.lastPercent = oldValue || 0
|
|
this._activeAnimation()
|
|
}
|
|
},
|
|
created () {
|
|
this._activeAnimation()
|
|
},
|
|
methods: {
|
|
_activeAnimation () {
|
|
if (this.active) {
|
|
this.currentPercent = this.activeMode === VALUES.activeMode ? 0 : this.lastPercent
|
|
this.strokeTimer = setInterval(() => {
|
|
if (this.currentPercent + 1 > this.realPercent) {
|
|
this.currentPercent = this.realPercent
|
|
this.strokeTimer && clearInterval(this.strokeTimer)
|
|
} else {
|
|
this.currentPercent += 1
|
|
}
|
|
}, 30)
|
|
} else {
|
|
this.currentPercent = this.realPercent
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
<style>
|
|
uni-progress {
|
|
display: -webkit-flex;
|
|
display: flex;
|
|
-webkit-align-items: center;
|
|
align-items: center;
|
|
}
|
|
|
|
uni-progress[hidden] {
|
|
display: none;
|
|
}
|
|
|
|
.uni-progress-bar {
|
|
-webkit-flex: 1;
|
|
flex: 1;
|
|
}
|
|
|
|
.uni-progress-inner-bar {
|
|
width: 0;
|
|
height: 100%;
|
|
}
|
|
|
|
.uni-progress-info {
|
|
margin-top: 0;
|
|
margin-bottom: 0;
|
|
min-width: 2em;
|
|
margin-left: 15px;
|
|
font-size: 16px;
|
|
}
|
|
</style>
|
|
|