stroke-dashoffset 是唯一靠谱的控制方式,因其直接映射进度语义:从周长值减至0实现0%→100%平滑展开,而 stroke-dasharray 不支持插值动画且逻辑不符。

直接用 stroke-dashoffset 控制偏移量,配合固定 stroke-dasharray 和 transform: rotate(-90deg),就能做出平滑、可响应的环形加载动画;纯 CSS 动画只适合固定时长的 loading,动态进度必须靠 JS 更新内联样式。
为什么 stroke-dashoffset 是唯一靠谱的控制方式
SVG 圆的描边默认从 3 点钟方向(0°)开始顺时针绘制。stroke-dashoffset 移动的是“虚线起点”,不是“画多长”。当它从周长值减到 0,视觉上就是描边从“完全不可见”逐步“展开成整圈”——这天然对应 0% → 100% 的进度语义。
常见错误是试图动画 stroke-dasharray(比如从 "0,314" 到 "314,314"),结果要么闪一下,要么不动。因为浏览器不支持 dasharray 的插值动画,且逻辑上也不对:它定义的是“实线段+空白段”的重复模式,不是“长度”。
-
stroke-dasharray必须设为"C,C"(C 是精确周长),不能写死"100,100"或带单位如"100px,100px" - 周长 C =
2 * Math.PI * r,例如r="45"→ C ≈282.74,保留小数点后两位即可 - 初始
stroke-dashoffset设为 C,终点为 0;JS 动态更新时用offset = C * (1 - progress / 100)
必须加 transform: rotate(-90deg) 吗
必须加,且必须写在 <circle></circle> 标签的 transform 属性里,不能只靠 CSS 类。不加的话,动画从右侧开始绕,人在顶部看会觉得“起点错位”,尤其在移动端非常违和。
这个旋转是 SVG 坐标系的固有行为:默认起点是正右方(极角 0°),rotate(-90) 把整个圆逆时针转 90°,让起点落到正上方(12 点钟),符合直觉。
- 写法示例:
<circle cx="50" cy="50" r="45" transform="rotate(-90 50 50)" ...></circle> - 注意 rotate 的中心点要匹配
cx/cy,否则会偏移 - 如果同时用 CSS
transition控制stroke-dashoffset和transform,两个属性必须一起声明在 transition 中,否则描边和旋转不同步,出现撕裂感
JS 动态更新时最容易踩的坑
很多人把 stroke-dashoffset 写进 CSS 变量再用 style.setProperty 更新,但在 Safari 旧版或 IE11 中不生效——因为这些浏览器不支持 CSS 变量注入 SVG 属性。
最稳的方式是直接操作 DOM 属性:
- 用
element.setAttribute('stroke-dashoffset', offset),不是style.strokeDashoffset(后者在部分 Safari 下无效) - 确保 SVG 有明确
viewBox,例如viewBox="0 0 100 100",否则某些 Safari 版本会忽略r计算周长 - 别漏掉基础样式:
stroke(颜色)、stroke-width(粗细)、fill="none"(填充必须透明,否则盖住描边) - 动画卡顿?检查是否误启了
shape-rendering: crispEdges,它会禁用抗锯齿并干扰 dash 渲染,关掉即可
真正难的不是写对一次动画,而是让多个环形条在不同设备、不同进度下都保持起始点对齐、过渡顺滑、不跳变——这要求每次更新都基于同一套周长计算,并严格统一单位(全用数值,不用 % 或 em)。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











