效果图
创建组件
<template>
<view :style="[fsObj]">
<view class="progress-circle1" v-if="progressType == 1 || isFloat">
<svg>
<circle stroke="var(--inactive-color)" />
<circle stroke="var(--color)" class="progress-value"
style="stroke-dasharray: calc(2 * 3.1415 * var(--r) * (var(--percent) / 100)), 1000" />
</svg>
</view>
<view class="progress-circle2" v-else>
<svg>
<circle stroke="var(--inactive-color)" />
<circle stroke="var(--color)" class="progress-value"
style="stroke-dasharray: calc(2 * 3.1415 * var(--r) * (var(--percent) / 100)), 1000" />
</svg>
</view>
</view>
</template>
<script>
export default {
name: "progress-circle",
props: {
percent: {
type: Number,
default: 0
},
size: {
type: String,
default: '72px'
},
borderWidth: {
type: String,
default: '9px'
},
color: {
type: String,
default: '#E54242'
},
inactiveColor: {
type: String,
default: '#ccc'
},
type: {
type: String,
default: 1
}
},
data() {
return {
fsObj: {
'--percent': 0,
'--int': 0,
'--floatInt': 0,
'--size': '72px',
'--border-width': '9px',
'--color': '#E54242',
'--inactive-color': '#ccc'
},
progressType: 1,
isFloat: false
};
},
watch: {
percent: {
handler(newVal, oldVal) {
if(newVal) {
this.fsObj['--percent'] = newVal
this.fsObj['--int'] = Math.floor(newVal)
this.fsObj['--floatInt'] = parseInt((newVal - Math.floor(newVal))*100)
this.isFloat = parseInt((newVal - Math.floor(newVal))*100) > 0 ? true : false
}
},
immediate: true
},
size: {
handler(newVal, oldVal) {
if(newVal) {
this.fsObj['--size'] = newVal
}
},
immediate: true
},
borderWidth: {
handler(newVal, oldVal) {
if(newVal) {
this.fsObj['--border-width'] = newVal
}
},
immediate: true
},
color: {
handler(newVal, oldVal) {
if(newVal) {
this.fsObj['--color'] = newVal
}
},
immediate: true
},
inactiveColor: {
handler(newVal, oldVal) {
if(newVal) {
this.fsObj['--inactive-color'] = newVal
}
},
immediate: true
},
type: {
handler(newVal, oldVal) {
if(newVal) {
this.progressType = Number(newVal)
}
},
immediate: true
}
},
methods: {
}
}
</script>
<style lang="scss">
.progress-circle1, .progress-circle2 {
position: relative;
width: var(--size);
height: var(--size);
border-radius: 50%;
}
.progress-circle1::before {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
counter-reset: progress1 var(--int) progress2 var(--floatInt);
content: counter(progress1) '.' counter(progress2, decimal-leading-zero) '%';
white-space: nowrap;
font-size: 24rpx;
}
.progress-circle2::before {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
counter-reset: progress var(--int);
content: counter(progress) '%';
white-space: nowrap;
font-size: 24rpx;
}
.progress-circle1>svg, .progress-circle2>svg {
width: 100%;
height: 100%;
transform: rotate(-90deg);
}
.progress-circle1 circle, .progress-circle2 circle {
--r: calc((var(--size) - var(--border-width)) / 2);
cx: calc(var(--size) / 2);
cy: calc(var(--size) / 2);
r: var(--r);
fill: none;
stroke-width: var(--border-width);
stroke-linecap: round;
transition: stroke-dasharray .4s linear, stroke .3s;
}
.progress-value {
opacity: var(--percent);
}
</style>