<template>
<div :class="hasMask?'hasmask':''">
<svg ref="svg" :class="['yh-progress-box',hasMask?'hasmask':'']" :style="{height:sizeOut*2+'px',width:sizeOut*2+'px',backgroundColor:colorBg}">
<circle cx="75" cy="75" :r="sizeIn" fill="transparent" :stroke="colorBottom" :stroke-width="size" :stroke-dasharray="2*sizeIn*3.14"
stroke-dashoffset="0" class="yh-progress-bottom" :style="{transformOrigin:`${sizeOut}px 75px`,width:sizeIn*2+'px',height:sizeIn*2+'px'}"></circle>
<circle cx="75" cy="75" :r="sizeIn" fill="transparent" :stroke="colorTop" :stroke-width="size" :stroke-dasharray="2*sizeIn*3.14"
:stroke-dashoffset="show" class="yh-progress-top" :style="{transformOrigin:`${sizeOut}px 75px`,width:sizeIn*2+'px',height:sizeIn*2+'px'}" >
</circle>
<text :x="sizeOut" :y="sizeOut" text-anchor="middle" :fill="percentageColor" :font-size="percentageSize" font-weight="600">
{{percentage}}%
</text>
<text :x="sizeOut" :y="sizeOut+percentageSize" text-anchor="middle" :font-size="textSize" :fill="textcolor">
{{text}}
</text>
</svg>
</div>
</template>
<script>
function CheckIsColor(bgVal) {
let type='';
if(/^rgb\(/.test(bgVal)){
//如果是rgb开头,200-249,250-255,0-199
type = "^[rR][gG][Bb][\(]([\\s]*(2[0-4][0-9]|25[0-5]|[01]?[0-9][0-9]?)[\\s]*,){2}[\\s]*(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)[\\s]*[\)]{1}$";
}else if(/^rgba\(/.test(bgVal)){
//如果是rgba开头,判断0-255:200-249,250-255,0-199 判断0-1:0 1 1.0 0.0-0.9
type = "^[rR][gG][Bb][Aa][\(]([\\s]*(2[0-4][0-9]|25[0-5]|[01]?[0-9][0-9]?)[\\s]*,){3}[\\s]*(1|1.0|0|0.[0-9])[\\s]*[\)]{1}$";
}else if(/^#/.test(bgVal)){
//六位或者三位
type = "^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$"
}else if(/^hsl\(/.test(bgVal)){
//判断0-360 判断0-100%(0可以没有百分号)
type = "^[hH][Ss][Ll][\(]([\\s]*(2[0-9][0-9]|360|3[0-5][0-9]|[01]?[0-9][0-9]?)[\\s]*,)([\\s]*((100|[0-9][0-9]?)%|0)[\\s]*,)([\\s]*((100|[0-9][0-9]?)%|0)[\\s]*)[\)]$";
}else if(/^hsla\(/.test(bgVal)){
type = "^[hH][Ss][Ll][Aa][\(]([\\s]*(2[0-9][0-9]|360|3[0-5][0-9]|[01]?[0-9][0-9]?)[\\s]*,)([\\s]*((100|[0-9][0-9]?)%|0)[\\s]*,){2}([\\s]*(1|1.0|0|0.[0-9])[\\s]*)[\)]$";
}
let re = new RegExp(type);
if (bgVal.match(re) == null){
return false
}else{
return true
}
}
export default {
name:'progressBar',
props:{
sizeOut:{
type:Number,
default:100
},
sizeIn:{
type:Number,
default:80,
},
size:{
type:Number,
default:10
},
colorBg:{
type:String,
default:'#fff',
validator:function(value){
CheckIsColor(value)
}
},
colorTop:{
type:String,
default:'#0f0',
validator:function(value){
CheckIsColor(value)
}
},
colorBottom:{
type:String,
default:'#ccc',
validator:function(value){
CheckIsColor(value)
}
},
target:{
type:Number,
default:0
},
total:{
type:Number,
default:100
},
index:{
type:Number,
default:0
},
text:{
type:String,
default:'进行中'
},
textSize:{
type:Number,
default:20
},
textcolor:{
type:String,
default:'#f50',
validator:function(value){
CheckIsColor(value)
}
},
percentageSize:{
type:Number,
default:30,
},
percentageColor:{
type:String,
default:'#ff6321',
validator:function(value){
CheckIsColor(value)
}
},
hasMask:{
type:Boolean,
default:false
},
encumbrances:{
type:Number,
default:2
}
},
computed:{
show: function(){
if(this.target){
return ((100-this.target)*2*this.sizeIn*3.14/100).toFixed(this.encumbrances)
}else{
return ((1-this.index/this.total)*2*this.sizeIn*3.14).toFixed(this.encumbrances)
}
},
percentage: function(){
if(this.target){
return this.target.toFixed(this.encumbrances)
}else{
return ((this.index/this.total)*100).toFixed(this.encumbrances)
}
}
},
}
</script>
<style lang="less">
.yh-progress-box{
position: relative;
border-radius: 50%;
.yh-progress-bottom,.yh-progress-top{
position: absolute;
z-index: inherit;
transform: rotate(-90deg);
}
}
.hasmask{
width: 100%;
height: 100%;
background-color:rgba(0, 0, 0, 0.3);
position: fixed;
top: 0;
left: 0;
.yh-progress-box{
top: 50%;
left:50%;
transform: translate(-50%,-50%);
}
}
</style>
测试用例
<template>
<progress-bar :sizeOut="100" :index="20" :total="100" />
</template>
<script>
import progressBar from '@/components/progress-bar'
export default {
components:{
progressBar
}
}
</script>