uni-app环形进度条推荐SVG方案,因Canvas存在重绘难、兼容差、易内存泄漏等问题;SVG用stroke-dasharray与stroke-dashoffset控制弧长,配合rotate(-90)确保12点起始,兼容性好且平滑。
uni-app 没有内置圆形(环形)进度条,<uni-progress></uni-progress> 只支持线性,必须自己实现;优先选 svg 方案,比 css 旋转更稳,比 canvas 更轻、更易维护。
为什么不用 Canvas 实现环形进度条
Canvas 在 uni-app 中重绘需手动调用 uni.createCanvasContext + draw(),data 变化不会自动触发重绘;小程序端 canvasToTempFilePath 在 H5 不回调;v-for 列表中大量复用易内存泄漏;低端安卓机上 ctx.setLineWidth() 失效,线条可能极细或消失。
- 常见错误现象:
ctx.arc()起始角写0、结束角写30→ 弧度没换算,画出来只是一小段或方向反(逆时针) - 必须设
ctx.lineWidth和ctx.strokeStyle,且起始角建议固定为-Math.PI / 2(12 点钟方向) - 结束角 =
-Math.PI / 2 + 2 * Math.PI * progress,才能保证 0%→100% 对应 0°→360° 顺时针增长
SVG 方案:用 stroke-dasharray 和 stroke-dashoffset 算弧长
这是最推荐的方案:不依赖 JS 动画帧,CSS 控制 transition 即可平滑变化,iOS/安卓/H5 兼容性好,无旋转失真问题。
- 核心公式:圆周长 =
2 * Math.PI * r,即最大stroke-dasharray值;进度 60% 时,stroke-dashoffset = (1 - 0.6) * 周长 - 注意
<circle></circle>的transform="rotate(-90)",否则进度从 3 点钟方向开始(默认起点) - 描边宽度
stroke-width会影响视觉粗细,但不参与周长计算 —— 周长只和r有关
CSS 分半圆旋转方案:适合简单场景但坑多
把圆拆成左右两个半圆,分别用 transform: rotate() 控制显示范围。性能好、代码短,但逻辑绕、易出错。
- 左半圆负责 0%–50%,右半圆负责 50%–100%;超过 50% 后左半圆要锁死在 180°,只动右半圆
- 关键细节:左半圆要加
left: 0,让 transform 绕左侧中点转;右半圆对应加right: 0 - 动画跳变常见于 iOS WebView 或低配安卓机:旋转角度计算错位、
overflow: hidden裁剪失效、父容器未设position: relative
插件市场方案:快速上线但得看更新和兼容说明
直接用 DCloud 插件市场高星插件(如 uni-progress-circle 或 uni-rate-circle)能省时间,但务必检查两点:
- GitHub 最后更新时间是否在近半年内(2026 年 3 月后),避免用已停止维护的老版本
- 文档是否明确标注支持「微信小程序」+「App」+「H5」三端,有些插件只测了小程序,H5 下 SVG 渲染异常
- 插件内部若混用 Canvas + CSS,可能在多实例场景下出现样式污染或 canvas-id 冲突
真正难的不是画一个圆,而是让百分比变化时弧长计算不漂移、旋转不跳帧、不同屏幕尺寸下比例不缩放失真 —— 这些细节全藏在 r、stroke-width、transform 和 viewBox 的配合里。


















