vue实现扇形图表
使用 SVG 实现扇形图表
在 Vue 中可以通过 SVG 的 <path> 元素绘制扇形。SVG 的路径数据 (d 属性) 使用极坐标公式计算扇形的起点和终点。
扇形路径计算公式:
- 圆心坐标:
(cx, cy) - 半径:
r - 起始角度:
startAngle(需转换为弧度) - 结束角度:
endAngle(需转换为弧度)
路径生成函数:

function describeArc(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);
const largeArcFlag = endAngle - startAngle <= 180 ? 0 : 1;
return `M ${cx} ${cy} L ${x1} ${y1} A ${r} ${r} 0 ${largeArcFlag} 1 ${x2} ${y2} Z`;
}
Vue 组件实现
创建可复用的扇形组件,接收角度、颜色等参数:
<template>
<svg width="200" height="200" viewBox="0 0 200 200">
<path
:d="arcPath"
:fill="color"
stroke="#fff"
stroke-width="1"
/>
</svg>
</template>
<script>
export default {
props: {
startAngle: { type: Number, default: 0 },
endAngle: { type: Number, required: true },
color: { type: String, default: '#42b983' },
radius: { type: Number, default: 80 },
center: { type: Number, default: 100 }
},
computed: {
arcPath() {
return describeArc(
this.center,
this.center,
this.radius,
this.startAngle,
this.endAngle
);
}
}
};
function describeArc(cx, cy, r, startAngle, endAngle) {
// 同上文路径生成函数
}
</script>
组合多个扇形形成饼图
通过多个扇形组件组合,并动态计算每个扇形的起始角度:

<template>
<div class="pie-chart">
<Sector
v-for="(item, index) in data"
:key="index"
:start-angle="getStartAngle(index)"
:end-angle="getEndAngle(index)"
:color="item.color"
/>
</div>
</template>
<script>
import Sector from './Sector.vue';
export default {
components: { Sector },
data() {
return {
data: [
{ value: 30, color: '#FF6384' },
{ value: 50, color: '#36A2EB' },
{ value: 20, color: '#FFCE56' }
]
};
},
methods: {
getTotal() {
return this.data.reduce((sum, item) => sum + item.value, 0);
},
getStartAngle(index) {
if (index === 0) return 0;
return this.data.slice(0, index).reduce((sum, item) => {
return sum + (item.value / this.getTotal()) * 360;
}, 0);
},
getEndAngle(index) {
const prevSum = this.data.slice(0, index + 1).reduce((sum, item) => {
return sum + (item.value / this.getTotal()) * 360;
}, 0);
return prevSum;
}
}
};
</script>
添加交互效果
为扇形添加悬停效果和点击事件:
<template>
<path
:d="arcPath"
:fill="color"
stroke="#fff"
stroke-width="1"
@mouseenter="handleHover(true)"
@mouseleave="handleHover(false)"
@click="$emit('click')"
:style="hoverStyle"
/>
</template>
<script>
export default {
// ...其他代码
data() {
return {
isHovered: false
};
},
methods: {
handleHover(state) {
this.isHovered = state;
}
},
computed: {
hoverStyle() {
return {
transform: this.isHovered ? 'scale(1.05)' : 'scale(1)',
transformOrigin: 'center',
transition: 'transform 0.2s ease',
cursor: 'pointer'
};
}
}
};
</script>
使用第三方库
对于复杂需求,可以考虑使用专门的图表库:
这些库提供更完善的图表功能和动画效果,适合生产环境使用。






