SVG圆形进度环的周长应通过circle.getTotalLength()获取,而非手算2πr,以避免缩放导致的误差;stroke-dasharray需固定为该周长值,动画由stroke-dashoffset从周长值渐变至0实现。

SVG stroke-dasharray 怎么算出圆周长
圆形进度环本质是用 SVG 的 <circle></circle> 画一个空心圆,再靠 stroke-dasharray 截取一段“虚线”来当进度条。关键第一步:得知道这个圆的周长,否则 dasharray 值全错。
圆周长 = 2 * Math.PI * r,但注意——SVG 中 <circle></circle> 的 r 是属性值,而 CSS 动画里常靠 transform: scale() 或 viewBox 缩放,这时实际渲染半径可能已变。最稳的方式是直接在 JS 里读 SVG 元素的 getTotalLength():
const circle = document.querySelector('circle');
const circumference = circle.getTotalLength(); // ✅ 真实渲染周长,无视缩放/视口干扰- 别手算
2 * 3.1416 * 50然后硬写进 CSS,缩放后进度会漂移 - 如果 circle 没渲染完成就调
getTotalLength(),返回 0 —— 得等DOMContentLoaded或用requestAnimationFrame延迟一帧 -
viewBox="0 0 100 100"时,r="50"的圆周长 ≈ 314.16,但若父容器宽高不等或有 preserveAspectRatio,仍建议用getTotalLength()
为什么 stroke-dasharray 设成 circumference 还是没动画
设对了周长只是基础。真正驱动动画的是 stroke-dashoffset 的变化:它控制“虚线起点”往左偏移多少。初始值应为 circumference(整圈盖住),结束值为 0(完全露出)。
常见错误是只改 stroke-dasharray,或者 offset 初始/结束值反了:
立即学习“前端免费学习笔记(深入)”;
/* ❌ 错误:dasharray 变了,但 offset 没动,看起来像闪烁 */
.circle { stroke-dasharray: 314; animation: dash 2s; }
@keyframes dash { from { stroke-dasharray: 0; } to { stroke-dasharray: 314; } }
<p>/<em> ✅ 正确:固定 dasharray,只动 offset </em>/
.circle { stroke-dasharray: 314; stroke-dashoffset: 314; animation: draw 2s ease-in-out; }
@keyframes draw { from { stroke-dashoffset: 314; } to { stroke-dashoffset: 0; } }-
stroke-dasharray在整个动画中必须保持不变,否则浏览器要重绘路径,容易卡顿或跳变 - IE 不支持
stroke-dashoffset动画,需用@keyframes+ JS fallback 或直接放弃 IE - 动画时间短(如
0.3s)时,ease-in-out比linear更自然;但数值突变大时,linear反而更准
CSS 动画和 JS 控制进度哪个更靠谱
纯 CSS 动画适合固定时长、固定起止的场景(比如加载中转圈)。一旦要响应数据、暂停、倒退、动态更新进度,JS 是唯一选择。
核心逻辑就是实时改 stroke-dashoffset:
function setProgress(percent) {
const offset = circumference - (percent / 100) * circumference;
circle.style.strokeDashoffset = offset;
}
setProgress(75); // 进度 75%- 别用
circle.setAttribute('style', ...),会覆盖原有内联样式;用circle.style.xxx安全 - 百分比从 0→100 时,offset 从
circumference→0;反过来(倒退)就得反向计算 - 如果进度值来自 API,注意防抖——频繁调
setProgress会导致 layout thrashing - CSS 动画用
animation-play-state: paused能暂停,但 JS 改 style 是即时生效,没法“暂停”,得自己记状态
圆环粗细、颜色、旋转方向怎么微调
粗细靠 stroke-width,但要注意:增大 stroke-width 会让圆视觉上变大,尤其当 cx/cy 固定时,边缘可能被裁剪。稳妥做法是把 stroke-width 算进半径里:
比如想要外径 100px 的圆环,stroke-width: 8,那 r 应设为 46(即 100/2 - 8/2)。
- 顺时针动画是默认行为;逆时针需要加
transform: rotate(180deg)并调整stroke-dashoffset方向,不如直接翻转 SVG 坐标系 - 颜色过渡用
transition: stroke 0.3s即可,但不要和 dashoffset 动画共用同一 transition,易冲突 - 移动端 Safari 对
stroke-dashoffset动画有渲染延迟,加will-change: stroke-dashoffset可缓解
圆环动画看着简单,但真实项目里最常栽在周长没读准、offset 方向搞反、以及缩放后尺寸失真这三处。尤其当设计稿给的是“直径 80px”,而开发随手写 r="40" 却忘了父容器有 scale(0.9) —— 这时候 dasharray 再对也没用。


















