开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第5天,点击查看活动详情
ECharts 环形图
话不多说先上图。原本想通过极坐标柱状图的实现方式来实现上图效果,但结果不尽人意。下方提供两种展现形式,第一种是在Made A Pie 中展现,方便查看修改源代码,另一种方法是把项目下载下来在本地运行,适合项目本身就是vue搭建的同学。
方式一:Made A Pie 中展现
方式二:Vue3 项目中展现
Vue3 项目搭建参考地址:juejin.cn/post/716978…
完整项目地址(此文章所使用源码均出自该项目):gitee.com/zhaodapeng/…
1.实现思路
图中所有元素都是通过ECharts实现,并未使用贴图。外圈刻度效果使用的是仪表盘的刻度实现,环形背景线和进度条是通过拼接环饼图实现,类型名称则使用固定Y轴位置的方式实现。
2.组件封装
# components/echarts/EchartsComp.vue
<template>
<div id="echartsComp" :style="{ height: height, width: width }"></div>
</template>
<script>
import { getCurrentInstance } from "vue";
export default {
name: "EchartsComp",
props: {
options: {
type: Object,
required: true,
},
width: {
type: String,
default: "200px",
},
height: {
type: String,
default: "200px",
},
},
mounted() {
// 渲染图表
const { proxy } = getCurrentInstance();
this.chart = proxy.$echarts.init(document.getElementById("echartsComp"));
this.chart.setOption(this.options);
// 事件
this.chart.on("click", function (params) {
console.log(params);
});
},
methods: {
Refresh() {
console.log(this.options);
this.chart.setOption(this.options);
},
},
};
</script>
3.代码实现
将数据和逻辑抽离,通过数据来生成配置项。目前是四组数据,如需增加数据组数,需要对类型名称的位置另做调整。
# views/echarts/RingDiagram.vue
<template>
<div class="contBody">
<h2 class="title" @click="handleTab">环形图(点击更换数据)</h2>
<!-- echarts 环形图 -->
<EchartsComp
class="ringBar"
ref="chart"
:options="ringDiagramOptions"
width="100%"
height="600px"
/>
</div>
</template>
<script>
import EchartsComp from "@/components/echarts/EchartsComp.vue";
export default {
name: "RingDiagramPage",
data() {
return {
ringDiagramOptions: {},
ringDiagramData: [
{
name: "本科",
value: 300,
},
{
name: "硕士",
value: 350,
},
{
name: "大专",
value: 400,
},
{
name: "博士",
value: 150,
},
],
};
},
components: { EchartsComp },
created() {
this.init();
},
methods: {
init() {
// 最大值
this.sumValue = 500;
const optionData = this.getData(this.ringDiagramData);
this.ringDiagramOptions = {
backgroundColor: "RGB(8,20,67)",
color: [
{
type: "linear",
x: 0,
y: 0,
x2: 1,
y2: 1,
colorStops: [
{
offset: 0,
color: "rgba(10,31,95,1)",
},
{
offset: 1,
color: "rgba(1,232,254,1)",
},
],
global: false,
},
],
grid: {
top: "16%",
bottom: "54%",
left: "50%",
containLabel: false,
},
yAxis: [
{
type: "category",
inverse: true,
z: 3,
axisLine: {
show: false,
},
axisTick: {
show: false,
},
axisLabel: {
interval: 0,
inside: false,
textStyle: {
color: "RGB(78,184,252)",
fontSize: 20,
},
show: true,
},
data: optionData.yAxis,
},
],
xAxis: [
{
show: false,
},
],
series: optionData.series,
};
},
getData(data) {
let res = {
series: [
{
name: "大环",
type: "gauge",
splitNumber: 15,
radius: "92%",
center: ["50%", "55%"],
startAngle: 90,
endAngle: -270,
axisLine: {
show: false,
lineStyle: {
color: [[1, "#1f59a7"]],
},
},
axisTick: {
show: false,
},
splitLine: {
show: true,
length: 32,
lineStyle: {
color: "auto",
width: 3.5,
},
},
axisLabel: {
show: false,
},
detail: {
show: false,
},
},
{
name: "小环",
type: "gauge",
splitNumber: 15,
radius: "88%",
center: ["50%", "55%"],
startAngle: 90,
endAngle: -269.9999,
axisLine: {
show: false,
},
axisTick: {
show: true,
lineStyle: {
color: "#1f59a7",
width: 3,
},
length: 20,
splitNumber: 5,
},
splitLine: {
show: false,
},
axisLabel: {
show: false,
},
detail: {
show: false,
},
},
],
yAxis: [],
};
for (let i = 0; i < data.length; i++) {
res.series.push({
name: "学历",
type: "pie",
clockWise: true,
z: 2,
hoverAnimation: false,
radius: [73 - i * 15 + "%", 68 - i * 15 + "%"],
center: ["50%", "55%"],
label: {
show: true,
formatter: "{d}%",
color: "RGB(246,175,101)",
fontSize: 20,
position: "inside",
},
labelLine: {
show: false,
},
data: [
{
value: data[i].value,
name: data[i].name,
},
{
value: this.sumValue - data[i].value,
name: "",
itemStyle: {
color: "rgba(0,0,0,0)",
borderWidth: 0,
},
tooltip: {
show: false,
},
label: {
show: false,
},
hoverAnimation: false,
},
],
});
res.series.push({
name: "背景线",
type: "pie",
silent: true,
z: 1,
clockWise: true,
hoverAnimation: false,
radius: [71 - i * 15 + "%", 69 - i * 15 + "%"],
center: ["50%", "55%"],
label: {
show: false,
},
itemStyle: {
label: {
show: false,
},
labelLine: {
show: false,
},
borderWidth: 5,
},
data: [
{
value: 100,
itemStyle: {
color: "RGB(12,64,128)",
borderWidth: 0,
},
tooltip: {
show: false,
},
hoverAnimation: false,
},
],
});
res.yAxis.push(data[i].name);
}
return res;
},
async handleTab() {
// 数据更新
this.ringDiagramData = [
{
name: "本科",
value: this.getNum(350, 400),
},
{
name: "硕士",
value: this.getNum(300, 350),
},
{
name: "大专",
value: this.getNum(250, 300),
},
{
name: "博士",
value: this.getNum(100, 150),
},
];
await this.init();
this.$refs.chart.Refresh();
},
// 生成随机数
getNum(min, max) {
const num = parseInt(Math.random() * (max - min + 1) + min);
return Math.floor(num);
},
},
};
</script>
<style scoped>
.contBody {
width: 100%;
box-sizing: border-box;
}
.contBody .title {
padding: 0 0 24px;
}
</style>