用svg画可控制环形进度条需用配合stroke-dasharray与stroke-dashoffset:先计算周长(2πr或gettotallength()),设stroke-dasharray="circumference,circumference",stroke-dashoffset从周长渐变至0,并加transform="rotate(-90 cx cy)"使起点在顶部,再通过js动态更新offset值实现精确进度控制。

怎么用 SVG 画一个可控制的环形进度条?
环形进度条本质是用 <circle></circle> 或 <path></path> 绘制圆弧,再通过 stroke-dasharray 和 stroke-dashoffset 控制“已填充”长度。关键不是画圆,而是把「百分比」映射到「圆周长度」上。
SVG 圆默认是顺时针从 3 点钟方向开始画,但进度条习惯从 12 点钟方向(顶部)开始——得靠 transform 旋转 -90° 对齐。
示例代码核心逻辑:
<svg width="120" height="120" viewbox="0 0 120 120"><circle cx="60" cy="60" r="50" fill="none" stroke="#e0e0e0" stroke-width="8"></circle><circle cx="60" cy="60" r="50" fill="none" stroke="#4CAF50" stroke-width="8" stroke-dasharray="314.16" stroke-dashoffset="62.83" transform="rotate(-90 60 60)"></circle></svg>
stroke-dasharray="314.16" 是圆周长(2 × π × r ≈ 2 × 3.1416 × 50),stroke-dashoffset 决定起点偏移量:值越小,显示越长。62.83 = 314.16 × (1 − 0.8),对应 80% 进度。
怎么用 JS 动态更新 SVG 环形进度?
不能直接改 stroke-dashoffset 的数值,必须先算出当前进度对应的偏移量,再设给 DOM 元素。常见错误是忘记重置 offset、或没处理动画过渡。
- 用
getTotalLength()获取真实路径长度(比手算更可靠,尤其用了stroke-width或非整数半径时) - offset = 总长 × (1 − 进度),例如进度 35%,offset = total × 0.65
- 加
transition: stroke-dashoffset 0.3s ease到<circle></circle>上才能有动画效果 - 别在每次更新时重新创建
<circle></circle>,直接setAttribute()更轻量
简单 JS 示例:
const circle = document.querySelector('circle:last-of-type');
const radius = 50;
const circumference = 2 * Math.PI * radius;
circle.style.strokeDasharray = `${circumference}`;
circle.style.strokeDashoffset = circumference;
<p>function setProgress(percent) {
const offset = circumference - (percent / 100) * circumference;
circle.style.strokeDashoffset = offset;
}
setProgress(75); // 更新为 75%</p>
为什么进度条转半圈就卡住?常见 SVG 坐标/旋转陷阱
最常踩的坑是没对齐起始角度,导致视觉上“只走一半”或“反向跑”。SVG 的 <circle></circle> 没有内置“起点”属性,全靠 transform 和 stroke-dashoffset 配合。
- 不加
transform="rotate(-90 60 60)":进度从 3 点钟方向开始,和 UI 设计稿对不上 - 加了 rotate 但没指定中心点(如写成
rotate(-90)):整个圆绕左上角转,图形错位 - 用
<path d="M... A..."></path>手写圆弧时,large-arc-flag设错会导致只画半圆甚至不显示 - 父容器
overflow: hidden且 SVG 未设viewBox:旋转后部分圆被裁掉,看起来像“断了”
要不要用 CSS 自定义属性驱动 SVG 进度?
可以,但有限制:CSS 变量能传进 SVG 的 style 属性,但不能直接绑定到 stroke-dashoffset 的计算逻辑里。你仍需 JS 把变量读出来、算 offset、再设回去。
不过用 CSS 变量统一管理颜色、尺寸、动画时长很实用:
svg { --progress-color: #2196F3; --track-color: #f5f5f5; --duration: 0.4s; }
circle:nth-child(2) {
stroke: var(--progress-color);
transition: stroke-dashoffset var(--duration) ease;
}
真正动态响应用户输入或 API 数据时,JS 仍是主力。CSS 变量适合主题切换或配置复用,别指望它替代 JS 的计算能力。
环形进度条的复杂点不在绘图,而在角度对齐、长度计算、动画触发时机这三处。哪怕只是改个半径,也得同步更新 viewBox、cx/cy、getTotalLength() 调用位置——漏一个,进度就“歪”了。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











