当前位置:首页 > VUE

vue实现扇形进度

2026-02-17 04:18:02VUE

Vue 实现扇形进度条

使用 SVG 绘制扇形

SVG 提供了一种灵活的方式来绘制扇形进度条。可以通过 path 元素结合 d 属性动态生成扇形路径。

<template>
  <svg width="200" height="200" viewBox="0 0 200 200">
    <path
      :d="getArcPath(progress)"
      fill="#4CAF50"
      stroke="#FFFFFF"
      stroke-width="2"
    />
    <text x="100" y="100" text-anchor="middle" dominant-baseline="middle">
      {{ progress }}%
    </text>
  </svg>
</template>

<script>
export default {
  props: {
    progress: {
      type: Number,
      default: 0,
      validator: (value) => value >= 0 && value <= 100,
    },
  },
  methods: {
    getArcPath(progress) {
      const radius = 90;
      const centerX = 100;
      const centerY = 100;
      const angle = (progress / 100) * 360;
      const startAngle = -90;
      const endAngle = startAngle + angle;

      const startRad = (startAngle * Math.PI) / 180;
      const endRad = (endAngle * Math.PI) / 180;

      const x1 = centerX + radius * Math.cos(startRad);
      const y1 = centerY + radius * Math.sin(startRad);
      const x2 = centerX + radius * Math.cos(endRad);
      const y2 = centerY + radius * Math.sin(endRad);

      const largeArcFlag = angle > 180 ? 1 : 0;

      return `M ${centerX} ${centerY} L ${x1} ${y1} A ${radius} ${radius} 0 ${largeArcFlag} 1 ${x2} ${y2} Z`;
    },
  },
};
</script>

使用 CSS 和 HTML 实现

CSS 的 conic-gradient 可以用于创建扇形进度条,但需要注意浏览器兼容性。

vue实现扇形进度

<template>
  <div class="progress-container">
    <div class="progress-fill" :style="fillStyle"></div>
    <div class="progress-text">{{ progress }}%</div>
  </div>
</template>

<script>
export default {
  props: {
    progress: {
      type: Number,
      default: 0,
      validator: (value) => value >= 0 && value <= 100,
    },
  },
  computed: {
    fillStyle() {
      return {
        background: `conic-gradient(#4CAF50 ${this.progress}%, transparent 0%)`,
      };
    },
  },
};
</script>

<style>
.progress-container {
  width: 200px;
  height: 200px;
  border-radius: 50%;
  position: relative;
  background: #f5f5f5;
}

.progress-fill {
  width: 100%;
  height: 100%;
  border-radius: 50%;
}

.progress-text {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-size: 24px;
  font-weight: bold;
}
</style>

使用 Canvas 绘制扇形

Canvas 提供了更底层的绘图能力,适合需要复杂动画的场景。

vue实现扇形进度

<template>
  <canvas ref="canvas" width="200" height="200"></canvas>
</template>

<script>
export default {
  props: {
    progress: {
      type: Number,
      default: 0,
      validator: (value) => value >= 0 && value <= 100,
    },
  },
  mounted() {
    this.drawProgress();
  },
  watch: {
    progress() {
      this.drawProgress();
    },
  },
  methods: {
    drawProgress() {
      const canvas = this.$refs.canvas;
      const ctx = canvas.getContext("2d");
      const centerX = canvas.width / 2;
      const centerY = canvas.height / 2;
      const radius = 90;
      const startAngle = -0.5 * Math.PI;
      const endAngle = startAngle + (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();

      ctx.font = "24px Arial";
      ctx.textAlign = "center";
      ctx.textBaseline = "middle";
      ctx.fillStyle = "#000000";
      ctx.fillText(`${this.progress}%`, centerX, centerY);
    },
  },
};
</script>

使用第三方库

对于更复杂的需求,可以考虑使用第三方库如 echartsd3.js

<template>
  <div ref="chart" style="width: 200px; height: 200px"></div>
</template>

<script>
import * as echarts from "echarts";

export default {
  props: {
    progress: {
      type: Number,
      default: 0,
      validator: (value) => value >= 0 && value <= 100,
    },
  },
  mounted() {
    this.initChart();
  },
  watch: {
    progress() {
      this.updateChart();
    },
  },
  methods: {
    initChart() {
      this.chart = echarts.init(this.$refs.chart);
      this.updateChart();
    },
    updateChart() {
      const option = {
        series: [
          {
            type: "pie",
            radius: ["70%", "90%"],
            avoidLabelOverlap: false,
            label: {
              show: true,
              position: "center",
              formatter: `${this.progress}%`,
              fontSize: 24,
              fontWeight: "bold",
            },
            data: [
              { value: this.progress, itemStyle: { color: "#4CAF50" } },
              { value: 100 - this.progress, itemStyle: { color: "#f5f5f5" } },
            ],
          },
        ],
      };
      this.chart.setOption(option);
    },
  },
};
</script>

动画效果

如果需要平滑的动画效果,可以使用 requestAnimationFrame 或 CSS 过渡。

// 在 SVG 或 Canvas 方法中添加动画
animateProgress(targetProgress) {
  const duration = 1000; // 动画时长
  const startTime = performance.now();
  const startProgress = this.progress;

  const animate = (currentTime) => {
    const elapsedTime = currentTime - startTime;
    const progress = Math.min(elapsedTime / duration, 1);
    this.progress = startProgress + (targetProgress - startProgress) * progress;
    if (progress < 1) {
      requestAnimationFrame(animate);
    }
  };
  requestAnimationFrame(animate);
}

以上方法可以根据具体需求选择,SVG 适合简单场景,Canvas 适合复杂动画,第三方库适合快速实现高级功能。

标签: 扇形进度
分享给朋友:

相关文章

vue实现环形进度组件

vue实现环形进度组件

实现环形进度组件 环形进度组件可以通过SVG或Canvas实现,以下是基于SVG的实现方法: 定义组件模板 <template> <div class="circle-p…

vue实现页面加载进度

vue实现页面加载进度

Vue 实现页面加载进度的方法 使用 NProgress 库 安装 NProgress 库: npm install nprogress 在 Vue 项目中引入并使用: import NPro…

css制作圆环扇形

css制作圆环扇形

使用CSS制作圆环扇形 方法一:使用border-radius和clip-path 通过设置border-radius创建圆形,再利用clip-path裁剪出扇形效果。 .circle-sector…

php实现快递进度

php实现快递进度

实现快递进度查询的PHP方法 使用快递鸟API 快递鸟提供物流查询API接口,支持多家快递公司。需注册账号获取API Key和商户ID。 // 配置参数 $appKey = '你的AppKey';…

vue前端实现下载进度

vue前端实现下载进度

实现下载进度显示的方法 在Vue中实现下载进度显示,可以通过监听XMLHttpRequest或fetch的progress事件来获取下载进度数据。以下是具体实现方式: 使用XMLHttpReque…

css制作扇形

css制作扇形

使用CSS制作扇形 通过CSS的clip-path属性可以轻松实现扇形效果。clip-path允许裁剪元素的显示区域,结合polygon()或circle()函数定义裁剪形状。 .sector {…