1.场景:UI设计给了四分之三环形弧百分比标注
之前开发用的是都是echarts完成的环形弧,接到需求后看了echarts文档也没找到相关的属性配置,后来查了很多资料,找到了解决方法。
2.实现方式
处理传给echart的数据
将数据处理成三部分
1.隐藏的部分占25%,将其设置为透明色,就是那个没显示的部分。
2.将完成的数据乘以75%(就是蓝色的环形部分)。
3.灰色的部分用100减去前面两部分。
const dealOption = val => {
let rate = (val.rate * 0.75).toFixed(2);
return [
{
value: rate,
originRate: val.rate,
name: "",
itemStyle: {
color: {
type: "linear",
x: 0,
y: 0,
x2: 1,
y2: 1,
colorStops: [
{
offset: 0,
color: "#90C9FF" // 0% 处的颜色
},
{
offset: 1,
color: "#549BFF" // 100% 处的颜色
}
],
globalCoord: true // 缺省为 false
}
}
},
{
value: 75 - rate,
name: "",
itemStyle: {
color: "#EAEFF5"
}
},
{
value: 25,
name: "",
itemStyle: {
color: "transparent"
}
}
];
};
echart组件代码
<template>
<div class="percentPieChart">
<div class="charCradContainer">
<div class="cont" ref="contRef">
<div class="empty" v-if="!option.length">
<span>暂无数据</span>
</div>
</div>
</div>
</div>
</template>
<script>
import * as echarts from "echarts";
import { defineComponent, toRefs, reactive, watch } from "@vue/composition-api";
export default defineComponent({
name: "percentPieChart",
props: {
title: {
type: String,
default: ""
},
option: {
default: () => [],
type: Array
},
count: {
type: String,
default: ""
},
info: {
type: String,
default: ""
}
},
setup(props, { refs, root }) {
const state = reactive({
myChart: null
});
const innerOption = () => {
if (props.option.length && !state.myChart) {
// 基于准备好的dom,初始化echarts实例
state.myChart = echarts.init(refs.contRef);
const option = {
title: {
text: `{a|${props.option[0].originRate}}{b|%}\n{c|评审通过率}`,
x: "center",
y: "center",
subtext: "",
textStyle: {
color: "#1496FF",
rich: {
a: {
fontSize: 27,
fontWeight: 700
},
b: {
fontSize: 16,
fontWeight: 700
},
c: {
fontSize: 12,
fontWeight: 500,
marginTop: 4
}
}
}
},
itemStyle: {
borderRadius: 15
},
series: [
{
name: props.title,
type: "pie",
radius: ["88%", "100%"],
center: ["50%", "50%"],
startAngle: 225,
avoidLabelOverlap: false,
labelLine: {
normal: {
show: false
}
},
data: props.option
}
]
};
// 使用刚指定的配置项和数据显示图表。
state.myChart.setOption(option);
} else if (state.myChart) {
state.myChart.setOption({
title: {
text: `${props.option[0].value / 0.75}%`
},
series: [
{
// 根据名字对应到相应的系列
name: props.title,
data: props.option
}
]
});
}
};
watch(
() => props.option,
() => {
if (props.option.length) {
root.$nextTick(() => {
innerOption();
});
}
},
{
immediate: true,
deep: true
}
);
return {
...toRefs(state),
innerOption
};
}
});
</script>
<style lang="less" scoped>
@w: 7.5vw;
.percentPieChart {
width: (230 / @w);
height: (230 / @w);
background: #f6f8fc;
margin: auto;
.undergraduateCharCardTitle {
padding-left: 0.4667rem;
font-size: 0.4267rem;
color: #32220e;
font-weight: 600;
line-height: 1.0667rem;
border-bottom: 1px solid #e5e5e5;
position: relative;
.iconR {
top: 0;
bottom: 0;
right: 0;
position: absolute;
width: 40px;
}
.iconR::before {
content: "";
position: absolute;
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAZBAMAAADztQLBAAAAGFBMVEUAAADAwMDAwMDCwsLb29vCwsK/v7/AwMBEhVBFAAAACHRSTlMA/YRTB084jrNSCvUAAAApSURBVAjXY2BhgIBABQidKAShmQWhAoZUECgUgfGh8uRzE4VQ3AtzPwCJ4gZ269ouTwAAAABJRU5ErkJggg==");
background-size: cover;
background-repeat: no-repeat;
background-position: center;
width: 0.2133rem;
height: 0.3467rem;
right: 0.2667rem;
top: 0;
bottom: 0;
margin: auto;
}
}
.charCradContainer {
position: relative;
width: 100%;
height: 100%;
.cont {
width: 100%;
height: 100%;
}
.contEmpty {
height: 0;
}
}
.empty {
background: #fff;
margin: auto;
padding-top: 20px;
padding-bottom: 20px;
width: 100%;
font-size: 14px;
color: #929194;
text-align: center;
span {
line-height: 30/75rem;
}
img {
display: block;
margin: 0 auto;
width: 24%;
height: 24%;
}
}
}
</style>