vue实现扇形图
Vue 实现扇形图的方法
使用 SVG 和 Vue 动态计算路径
通过 SVG 的 path 元素和 Vue 的计算属性动态生成扇形路径。以下是一个基础实现示例:
<template>
<svg width="200" height="200" viewBox="0 0 100 100">
<path
:d="sectorPath(50, 50, 40, 0, 90)"
fill="#FF6384"
/>
</svg>
</template>
<script>
export default {
methods: {
sectorPath(cx, cy, r, startAngle, endAngle) {
const startRad = (startAngle * Math.PI) / 180;
const endRad = (endAngle * Math.PI) / 180;
const x1 = cx + r * Math.cos(startRad);
const y1 = cy + r * Math.sin(startRad);
const x2 = cx + r * Math.cos(endRad);
const y2 = cy + r * Math.sin(endRad);
return `M ${cx} ${cy} L ${x1} ${y1} A ${r} ${r} 0 0 1 ${x2} ${y2} Z`;
}
}
};
</script>
使用第三方图表库(如 ECharts)
安装 ECharts 和 Vue-ECharts 封装库:
npm install echarts vue-echarts
示例代码:
<template>
<v-chart :option="chartOption" style="height: 400px"/>
</template>
<script>
import { use } from 'echarts/core';
import { PieChart } from 'echarts/charts';
import { CanvasRenderer } from 'echarts/renderers';
import VChart from 'vue-echarts';
use([PieChart, CanvasRenderer]);
export default {
components: { VChart },
data() {
return {
chartOption: {
series: [{
type: 'pie',
radius: ['50%', '70%'],
data: [
{ value: 35, name: 'Category A' },
{ value: 25, name: 'Category B' }
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}]
}
};
}
};
</script>
使用 Canvas 绘制
通过 Vue 的生命周期钩子和 Canvas API 实现:
<template>
<canvas ref="pieCanvas" width="300" height="300"></canvas>
</template>
<script>
export default {
mounted() {
this.drawPieChart();
},
methods: {
drawPieChart() {
const canvas = this.$refs.pieCanvas;
const ctx = canvas.getContext('2d');
const data = [30, 70];
const colors = ['#FF6384', '#36A2EB'];
let startAngle = 0;
data.forEach((value, i) => {
const sliceAngle = (2 * Math.PI * value) / 100;
ctx.beginPath();
ctx.fillStyle = colors[i];
ctx.moveTo(150, 150);
ctx.arc(150, 150, 100, startAngle, startAngle + sliceAngle);
ctx.closePath();
ctx.fill();
startAngle += sliceAngle;
});
}
}
};
</script>
响应式数据处理
结合 Vue 的响应式特性动态更新扇形图:
<template>
<div>
<svg width="200" height="200">
<path
v-for="(item, index) in sectors"
:key="index"
:d="item.path"
:fill="item.color"
/>
</svg>
<button @click="updateData">Update Data</button>
</div>
</template>
<script>
export default {
data() {
return {
data: [45, 30, 25],
colors: ['#FF6384', '#36A2EB', '#FFCE56']
};
},
computed: {
sectors() {
let total = this.data.reduce((a, b) => a + b, 0);
let startAngle = 0;
return this.data.map((value, i) => {
const angle = (value / total) * 360;
const path = this.sectorPath(100, 100, 80, startAngle, startAngle + angle);
startAngle += angle;
return { path, color: this.colors[i] };
});
}
},
methods: {
sectorPath(cx, cy, r, startAngle, endAngle) {
// 同第一个示例的 path 计算方法
},
updateData() {
this.data = this.data.map(() => Math.floor(Math.random() * 50) + 10);
}
}
};
</script>
关键注意事项
- SVG 方案适合轻量级定制需求,但需要手动计算几何路径
- ECharts 等库提供丰富的交互功能(如 tooltip、动画),适合复杂场景
- Canvas 方案性能较好,但需要手动处理分辨率适配
- 动态数据更新时,确保通过 Vue 的响应式系统触发重新渲染







