文章目录
效果图
css的原理
左右两边分开制作,左右两边各有两层盒子,外层负责遮挡溢出的部分,里层旋转表示百分比
template部分
// 圆环的代码
<div class="row rel">
<div class="left">
<div id="left" ref="left" class="leftCon" :style="{ backgroundColor: data.color }" />
</div>
<div class="right">
<div id="right" ref="right" class="rightCon" :style="{ backgroundColor: data.color }" />
</div>
<div class="circle" />
<div class="centerCircle">
{{ data.num }}%
</div>
</div>
js部分
<script setup>
import { onMounted, ref } from 'vue'
const props = defineProps({
data: {},
})
const left = ref(null)
const right = ref(null)
onMounted(() => {
const count = props.data.num
const totalcount = 100
left.value.style.transform = `rotate(${getLeftPercent(count, totalcount)}deg)`
right.value.style.transform = `rotate(${getRightPercent(count, totalcount)}deg)`
})
function getLeftPercent(count, totalcount) {
if (totalcount === 0 || count === 0 || count / totalcount <= 0.5)
return -180
else
return 180 * (((count / totalcount - 0.5) * 2) - 1)
}
function getRightPercent(count, totalcount) {
if (totalcount === 0 || count === 0)
return -180
else if (count / totalcount >= 0.5)
return 0
else
return 180 * (((count / totalcount) * 2) - 1)
}
</script>
css部分
.left,.right {
width: 50px;
height: 100px;
background: rgb(204, 204, 192);
overflow: hidden;
}
.left {
border-radius: 50px 0 0 50px;
}
.right {
border-radius: 0 50px 50px 0;
}
.rightCon {
width: 50px;
height: 100px;
border-radius: 0 100px 100px 0;
transform: rotate(-120deg);
transform-origin: left center;
}
.leftCon {
width: 50px;
height: 100px;
border-radius: 50px 0px 0px 50px;
transform: rotate(20deg);
transform-origin: right center;
}
.circle {
width: 90px;
height: 90px;
position: absolute;
left: 5px;
top: 5px;
border-radius: 50%;
background: rgb(251, 252, 251);
}
.rel {
position: relative;
}
.row {
display: flex;
flex-direction: row;
}
.centerCircle {
position : absolute;
border-radius: 50%;
width : 80px;
height : 80px;
transform : translate(10px, 10px);
display: flex;
justify-content: center;
align-items: center;
}