圆形进度条的核心是通过图形绘制展示百分比数值,不同实现方案在开发效率、定制空间上存在明显差异,开发者需要结合项目需求选择最合适的方案。

两种实现方案的核心差异
Element-UI是Vue生态中成熟的UI组件库,提供了封装好的el-progress组件,支持圆形进度条配置;原生JavaScript则可以通过SVG或者Canvas两种图形技术自行实现,不需要依赖第三方库。两者的核心差异主要体现在以下几个方面:
| 对比维度 | Element-UI实现 | 原生JavaScript实现 |
|---|---|---|
| 开发效率 | 高,直接配置属性即可 | 低,需要手写绘制逻辑 |
| 可定制性 | 中等,受组件内置样式限制 | 高,可完全自定义样式和交互 |
| 依赖成本 | 需要引入Element-UI库 | 无额外依赖 |
| 适用场景 | 后台管理系统、快速迭代项目 | 定制化前端项目、轻量页面 |
使用Element-UI实现圆形进度条
如果你的项目已经基于Vue框架并且引入了Element-UI,那么使用el-progress组件是最快捷的方式。只需要配置type为circle,再传入百分比数值即可完成基础功能。
基础实现代码
<template>
<div class="progress-container">
<!-- type设置为circle表示圆形进度条,percentage绑定进度值 -->
<el-progress
type="circle"
:percentage="currentPercent"
:width="120"
></el-progress>
<div class="control-btn">
<button @click="increase">增加进度</button>
<button @click="decrease">减少进度</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
currentPercent: 30 // 初始进度为30%
}
},
methods: {
// 增加进度,上限为100
increase() {
if (this.currentPercent < 100) {
this.currentPercent += 10
}
},
// 减少进度,下限为0
decrease() {
if (this.currentPercent > 0) {
this.currentPercent -= 10
}
}
}
}
</script>
<style scoped>
.progress-container {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
padding: 20px;
}
.control-btn {
display: flex;
gap: 15px;
}
button {
padding: 8px 16px;
cursor: pointer;
}
</style>
Element-UI的圆形进度条还支持自定义颜色、轨道宽度、显示文字等配置,只需要添加对应的属性即可,不需要修改底层绘制逻辑,非常适合不需要特殊样式的场景。
使用原生JavaScript实现圆形进度条
如果项目没有引入UI组件库,或者对进度条的样式、动画有特殊要求,那么使用原生JavaScript配合SVG或者Canvas实现会更合适。下面以SVG实现为例,SVG的矢量特性可以保证进度条在不同分辨率下都清晰显示。
SVG实现方案
SVG实现圆形进度条的核心是利用stroke-dasharray和stroke-dashoffset属性控制圆环的显示比例。stroke-dasharray定义虚线的每段长度和间距,stroke-dashoffset定义虚线起始位置的偏移量,通过调整偏移量就可以实现进度变化的效果。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>原生SVG圆形进度条</title>
<style>
.progress-wrap {
width: 200px;
margin: 50px auto;
text-align: center;
}
.progress-svg {
transform: rotate(-90deg); /* 让进度从顶部开始 */
}
.progress-text {
margin-top: 15px;
font-size: 18px;
}
button {
margin: 5px;
padding: 8px 15px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="progress-wrap">
<svg class="progress-svg" width="120" height="120">
<!-- 背景圆环 -->
<circle
cx="60"
cy="60"
r="50"
stroke="#e5e5e5"
stroke-width="10"
fill="none"
></circle>
<!-- 进度圆环 -->
<circle
id="progressCircle"
cx="60"
cy="60"
r="50"
stroke="#409eff"
stroke-width="10"
fill="none"
stroke-linecap="round"
stroke-dasharray="314.16" /* 圆周长 2*π*r ≈ 314.16 */
stroke-dashoffset="314.16" /* 初始偏移等于周长,进度为0 */
></circle>
</svg>
<div class="progress-text">当前进度:<span id="percentText">0</span>%</div>
<div>
<button onclick="changeProgress(10)">+10%</button>
<button onclick="changeProgress(-10)">-10%</button>
</div>
</div>
<script>
const circle = document.getElementById('progressCircle')
const percentText = document.getElementById('percentText')
const totalLength = 2 * Math.PI * 50 // 圆环周长
let currentPercent = 0
// 修改进度的函数
function changeProgress(step) {
currentPercent += step
// 限制进度在0-100之间
if (currentPercent < 0) currentPercent = 0
if (currentPercent > 100) currentPercent = 100
// 计算偏移量:周长 * (1 - 百分比)
const offset = totalLength * (1 - currentPercent / 100)
circle.style.strokeDashoffset = offset
percentText.textContent = currentPercent
}
// 初始化进度为30%
changeProgress(30)
</script>
</body>
</html>
Canvas实现方案
如果需要更复杂的动画效果,比如渐变颜色、动态粒子效果,Canvas会是更好的选择,不过Canvas的绘制逻辑会比SVG稍微复杂一些。
// 获取Canvas元素和上下文
const canvas = document.getElementById('progressCanvas')
const ctx = canvas.getContext('2d')
const centerX = canvas.width / 2
const centerY = canvas.height / 2
const radius = 50
const lineWidth = 10
let percent = 30
// 绘制圆形进度条的函数
function drawProgress(p) {
// 清空画布
ctx.clearRect(0, 0, canvas.width, canvas.height)
// 绘制背景圆环
ctx.beginPath()
ctx.arc(centerX, centerY, radius, 0, Math.PI * 2)
ctx.lineWidth = lineWidth
ctx.strokeStyle = '#e5e5e5'
ctx.stroke()
// 绘制进度圆环
ctx.beginPath()
// 进度从顶部开始,所以起始角度是-90度(Math.PI * 1.5)
const startAngle = Math.PI * 1.5
const endAngle = startAngle + (Math.PI * 2 * p / 100)
ctx.arc(centerX, centerY, radius, startAngle, endAngle)
ctx.lineWidth = lineWidth
ctx.strokeStyle = '#409eff'
ctx.lineCap = 'round'
ctx.stroke()
// 绘制中间文字
ctx.font = '18px Arial'
ctx.fillStyle = '#333'
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
ctx.fillText(`${p}%`, centerX, centerY)
}
// 初始绘制
drawProgress(percent)
// 进度变化函数
function changeCanvasProgress(step) {
percent += step
if (percent < 0) percent = 0
if (percent > 100) percent = 100
drawProgress(percent)
}
如何选择实现方案
实际开发中可以根据以下几点做选择:
- 如果项目已经使用Vue和Element-UI,且进度条没有特殊样式要求,优先选择Element-UI实现,能大幅减少开发时间
- 如果项目是轻量级的,没有引入任何UI库,或者需要兼容非Vue框架,原生JavaScript实现更合适,不会增加额外的包体积
- 如果需要高度定制进度条的样式,比如渐变色、特殊动画、交互效果,原生实现的可控性更强,能够满足各种个性化需求
- 如果需要考虑极端低版本浏览器兼容性,Element-UI的组件已经做了兼容性处理,而原生实现需要自己处理不同浏览器的API差异
两种方式没有绝对的好坏,核心是要匹配项目的实际需求和开发资源,选择成本最低、维护最方便的方案即可。
Element_UI原生JavaScript圆形进度条SVGCanvas修改时间:2026-07-14 02:33:44