vue实现扇形进度
Vue 实现扇形进度条
使用 SVG 绘制扇形
SVG 的 path 元素可以用于绘制扇形。通过计算扇形的路径数据,结合 Vue 的动态数据绑定实现进度变化。
<template>
<svg width="200" height="200" viewBox="0 0 100 100">
<path :d="getSectorPath(50, 50, 40, 0, endAngle)" fill="#4CAF50"/>
</svg>
</template>
<script>
export default {
data() {
return {
progress: 75, // 进度百分比 (0-100)
};
},
computed: {
endAngle() {
return (this.progress / 100) * 2 * Math.PI;
},
},
methods: {
getSectorPath(cx, cy, r, startAngle, endAngle) {
const x1 = cx + r * Math.cos(startAngle);
const y1 = cy + r * Math.sin(startAngle);
const x2 = cx + r * Math.cos(endAngle);
const y2 = cy + r * Math.sin(endAngle);
const largeArcFlag = endAngle - startAngle <= Math.PI ? 0 : 1;
return `M ${cx} ${cy} L ${x1} ${y1} A ${r} ${r} 0 ${largeArcFlag} 1 ${x2} ${y2} Z`;
},
},
};
</script>
使用 Canvas 绘制扇形
通过 Canvas 的 arc 方法绘制扇形,结合 Vue 的响应式特性更新绘制。
<template>
<canvas ref="canvas" width="200" height="200"></canvas>
</template>
<script>
export default {
data() {
return {
progress: 75,
};
},
mounted() {
this.drawSector();
},
watch: {
progress() {
this.drawSector();
},
},
methods: {
drawSector() {
const canvas = this.$refs.canvas;
const ctx = canvas.getContext('2d');
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const radius = 80;
const startAngle = 0;
const endAngle = (this.progress / 100) * 2 * Math.PI;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.moveTo(centerX, centerY);
ctx.arc(centerX, centerY, radius, startAngle, endAngle);
ctx.closePath();
ctx.fillStyle = '#4CAF50';
ctx.fill();
},
},
};
</script>
使用第三方库
可以借助第三方库如 vue-awesome-progress 或 echarts 快速实现扇形进度条。
使用 echarts 的示例:
<template>
<div ref="chart" style="width: 200px; height: 200px;"></div>
</template>
<script>
import * as echarts from 'echarts';
export default {
data() {
return {
progress: 75,
};
},
mounted() {
this.initChart();
},
watch: {
progress() {
this.initChart();
},
},
methods: {
initChart() {
const chart = echarts.init(this.$refs.chart);
chart.setOption({
series: [{
type: 'pie',
radius: ['60%', '80%'],
avoidLabelOverlap: false,
itemStyle: {
borderRadius: 0,
borderColor: '#fff',
borderWidth: 2
},
label: {
show: false,
},
data: [
{ value: this.progress, name: 'Progress' },
{ value: 100 - this.progress, name: 'Remaining' }
]
}]
});
},
},
};
</script>
动画效果
通过 CSS 或 JavaScript 为扇形进度条添加动画效果,提升用户体验。
// 在 drawSector 方法中添加动画
drawSector() {
const canvas = this.$refs.canvas;
const ctx = canvas.getContext('2d');
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const radius = 80;
let currentAngle = 0;
const targetAngle = (this.progress / 100) * 2 * Math.PI;
const animate = () => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.moveTo(centerX, centerY);
ctx.arc(centerX, centerY, radius, 0, currentAngle);
ctx.closePath();
ctx.fillStyle = '#4CAF50';
ctx.fill();
if (currentAngle < targetAngle) {
currentAngle += 0.05;
requestAnimationFrame(animate);
}
};
animate();
}

