效果:
组件封装的html部分
<template>
<div>
<div
class="ring_highlight"
:class="'ring_' + perToDeg"
>
<div class="ring_bgleft"></div>
<div class="ring_bgright"></div>
</div>
</div>
</template>
<script lang='ts' setup>
import { computed, defineProps } from 'vue'
let ringProps = defineProps({
percentageValue: {
type: Number,
default: 0
}
})
let perToDeg = computed (() => {
return Math.ceil(ringProps.percentageValue/100 * 360)
})
</script>
css部分
// 环形样式
.ringMixin(@bg) {
position: absolute;
width: 16px;
height: 16px;
transform: rotate(0deg);
border-radius: 50%;
background-color: @bg;
}
.ringDegMixin(@deg) {
.ring_bgleft when (@deg <= 180) {
.ringMixin(@theme-light);
clip: rect(0px, 8px, 16px, 0px);
transform: rotate(0deg);
}
.ring_bgleft when not (@deg <= 180) {
.ringMixin(@theme-warning);
clip: rect(0px, 8px, 16px, 0px);
transform: rotate(unit(-(360-@deg), deg));
}
.ring_bgright when (@deg <= 180) { // 锐角处理
.ringMixin(@theme-light);
clip: rect(0, 16px, 16px, 8px);
animation: ringRing 1s linear;
transform: rotate(unit(@deg, deg));
}
.ring_bgright when not (@deg <= 180) { // 钝角处理-高亮的部分跟锐角情况是对调的
.ringMixin(@theme-warning);
clip: rect(0, 16px, 16px, 8px);
transform: rotate(0deg);
}
}
.ring_highlight {
position: relative;
width: 16px;
height: 16px;
border-radius: 50%;
background-color: @theme-light;
&::after {
content: '';
width: 8px;
height: 8px;
border-radius: 50%;
position: absolute;
top: 4px;
left: 4px;
z-index: 9;
background-color: @theme-white;
}
}
.generate-ring(@n, @i: 0) when (@i =< @n) { // less中的循环函数
.ring_@{i} {
.ringDegMixin(@i);
&.ring_highlight when (@i <= 180) {
background-color: @theme-blue;
}
&.ring_highlight when not (@i <= 180) { // 超过50%的数据换一个颜色表示警告
background-color: @theme-warninglight;
}
}
.generate-ring(@n, (@i + 1));
}
.generate-ring(360); // 运行上面的循环函数,360个角度就可以覆盖一周的情况
// 组件调用
<PercentRing :percentage-value='30' /> // 占比30%
写完之后发现,antd里面有现成的环形进度条。。。可以直接用