一、ECharts 配置详解
1.1标题配置(中间文本)
title: {
text: `老人总数\n${total}`,
left: 'center',
top: '42%',
textStyle: {
color: '#fff',
fontSize: 16,
fontWeight: 'normal',
lineHeight: 24,
}
}
1.2 极坐标系核心配置
polar: {
radius: [40, 100], // 内环到外环半径范围
center: ['50%', '50%']
}
radius
控制环的内外大小(40~100 像素)
center
控制图表居中
angleAxis: {
max: 100,
clockwise: false,
show: false
}
max: 100
:表示角度按百分比计算(满圈)
clockwise: false
:环形从逆时针方向开始
show: false
:不显示角度坐标轴
radiusAxis: {
type: 'category',
show: false
}
极坐标的径向轴(环的分布方向)设为类别型,也隐藏。
1.3 系列数据渲染(关键)
series: list.map((item, index) => ({
type: 'bar',
data: [item.percent],
coordinateSystem: 'polar',
roundCap: true,
barWidth: 10,
z: index,
itemStyle: {
color: item.color
},
startAngle: index === 0 ? 0 : list[index - 1].percent,
endAngle: item.percent
}))
type: 'bar'
+coordinateSystem: 'polar'
=> 每一层为一个环形柱条
data: [item.percent]
:控制每一层占据的弧度(百分比)
roundCap: true
:每个环条两端为圆头
barWidth: 10
:每层环的宽度(10px)
z: index
:设置层级顺序,后渲染的在上层
color
:颜色来自数据项自定义
二、注意事项以及解释
什么是“极坐标系”?
我们平时看到的柱状图、折线图,都是用的“直角坐标系” —— 横轴是 X,竖轴是 Y。
而 极坐标系 是用“圆形”来表示数据的 —— 数据不是向上长,而是沿着圆圈展开。
你可以想象一块披萨:每一块就是一个“角度”,表示一个数据的占比
极坐标的两个坐标轴:
angleAxis
—— 控制“角度”,也就是每个环条占多少角度angleAxis: { max: 100, clockwise: false, show: false, } max: 100:表示整个圆为100%,用百分比来画。 clockwise: false:从左边开始画环,并逆时针转。 show: false:这个角度轴不显示出来(不然就一堆数字很丑)。
radiusAxis
—— 控制“半径”,决定这一条环是在哪一圈radiusAxis: { type: 'category', show: false, } type: 'category':代表我这里每一层圆都是“分类”用的,不是数值。 show: false:同样不显示。
想象多层披萨:
第一层是小圈圈(内层)
第二层是稍微大一点的圈(外层)
第三层更大...
这就是“多层圆”,而
radiusAxis
决定它是在第几层。怎么形成“多层圆”?
series: list.map((item, index) => ({ type: 'bar', data: [item.percent], coordinateSystem: 'polar', roundCap: true, barWidth: 10, z: index, itemStyle: { color: item.color }, })) list.map(...):我们有 4 种老人类型,就会画 4 个“圆圈圈”。 data: [item.percent]:这个值决定这个甜甜圈占圆圈的多少角度(比如 30%)。 barWidth: 10:每个圈的“厚度”是 10 像素。 为什么每一圈自动往外排? 因为 echarts 极坐标下,每画一个柱子,它会自动从里往外排列,每个 series 代表一层: series 0 → 最里面那圈 series 1 → 第二圈 series 2 → 第三圈 series 3 → 最外圈
3、全部代码
<template>
<div class="elderly-chart">
<div ref="chartRef" class="chart"></div>
<div class="info">
<div v-for="(item, index) in reversedList" :key="index" class="info-item">
<div class="info-color" :style="{ backgroundColor: item.color }"></div>
<div class="info-text">{{ item.name }}</div>
<div class="info-number">{{ item.number }}人</div>
<div class="info-percent">{{ item.percent }}%</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import * as echarts from 'echarts'
const chartRef = ref(null)
const list = [
{ name: '介助', number: 344, percent: 27, color: '#F2E93D' },
{ name: '介护', number: 304, percent: 37, color: '#4CE1D6' },
{ name: '失能', number: 98, percent: 7, color: '#C3A6FD' },
{ name: '自理', number: 485, percent: 93, color: '#2F7CF6' },
]
const reversedList = ref([...list].reverse())
onMounted(() => {
const chart = echarts.init(chartRef.value)
const total = 1231
const option = {
backgroundColor: 'transparent',
title: {
text: `老人总数\n${total}`,
left: 'center',
top: '42%',
textStyle: {
color: '#fff',
fontSize: 16,
fontWeight: 'normal',
lineHeight: 24,
},
},
polar: {
radius: [40, 100], // 保持内外半径范围不变
center: ['50%', '50%'],
},
angleAxis: {
max: 100, // 设置最大值为100,角度为百分比
clockwise: false,
show: false,
},
radiusAxis: {
type: 'category',
show: false,
},
series: list.map((item, index) => ({
type: 'bar',
data: [item.percent],
coordinateSystem: 'polar',
roundCap: true,
barWidth: 10,
z: index, // 控制层级
itemStyle: {
color: item.color,
},
// 动态设置每个环的占据角度
startAngle: index === 0 ? 0 : list[index - 1].percent, // 每个环的起始角度
endAngle: item.percent, // 每个环的结束角度
})),
}
chart.setOption(option)
window.addEventListener('resize', () => {
chart.resize()
})
})
</script>
<style scoped>
.elderly-chart {
display: flex;
align-items: center;
justify-content: center;
background: #0B1E38;
padding: 20px;
}
.chart {
width: 300px;
height: 300px;
position: relative;
}
.info {
margin-left: 30px;
display: flex;
flex-direction: column;
justify-content: center;
}
.info-item {
display: flex;
align-items: center;
margin-bottom: 12px;
}
.info-color {
width: 10px;
height: 10px;
border-radius: 50%;
margin-right: 8px;
}
.info-text {
color: #fff;
width: 50px;
}
.info-number {
color: #fff;
margin-left: 10px;
width: 60px;
}
.info-percent {
color: #fff;
margin-left: 10px;
}
</style>