环形进度动画本质是通过stroke-dasharray和stroke-dashoffset控制描边绘制过程,而非旋转或缩放;需设stroke-dasharray为周长、stroke-dashoffset从周长值渐变至0,并配合fill="none"、animation-fill-mode:forwards及css变量实现可复用、响应式效果。

用 stroke-dasharray 和 stroke-dashoffset 控制环形进度动画
SVG 圆环动画本质是“描边长度变化”,不是旋转或缩放。关键在两个属性:stroke-dasharray 定义虚线模式(这里设为圆周长),stroke-dashoffset 控制起始点偏移量。从满偏移到零,视觉上就是“环被擦除”——但反向理解:偏移量从大变小,就表现为“环被画出来”。
常见错误是直接对 transform: rotate() 动画,结果环转动但不增长;或者用 opacity 淡入,完全没进度感。
-
stroke-dasharray值必须等于圆的周长(2 * π * r),比如r=50→ 周长约314,设为314 -
stroke-dashoffset初始值设为314(完全不可见),动画终点设为0(完整显示) - 务必给
<circle></circle>设置fill="none",否则内部实心会遮盖动画效果
CSS 动画绑定到 SVG 元素的正确写法
不能把 @keyframes 直接套在 <svg></svg> 或 <g></g> 上再期望子元素响应——CSS 动画需作用于具体描边元素(即 <circle></circle> 本身)。
容易踩坑的是:用类名控制动画触发,但忘记重置 stroke-dashoffset 初始状态,导致第二次加载时动画不重放。
- 动画定义里必须显式写出
stroke-dashoffset的起止值,不能只写to部分 - 推荐用
animation-fill-mode: forwards保证动画结束后停留在终点状态 - 若需手动触发(如 AJAX 加载完成),用 JS 切换 class 比直接操作 style 更可控
@keyframes draw-ring {
from { stroke-dashoffset: 314; }
to { stroke-dashoffset: 0; }
}
.loading-circle {
animation: draw-ring 1.2s ease-out forwards;
}
适配不同尺寸和颜色的可复用方案
硬编码周长(如 314)会导致换尺寸后动画失效。实际项目中应通过 CSS 自定义属性解耦:
- 用
calc()计算周长:--circum: calc(2 * 3.1416 * var(--r)); - 把
--r设为变量,stroke-dasharray和stroke-dashoffset都引用它 - 颜色、线宽、动画时长全部抽成 CSS 变量,方便主题切换或 A/B 测试
- 注意:IE 不支持 CSS 变量,如需兼容,得用预处理器或 JS 注入
别忽略 stroke-linecap: round —— 它让环两端更圆润,否则尖角会破坏视觉连贯性。
配合 JavaScript 控制加载状态的边界处理
纯 CSS 动画只能做固定时长,真实场景要根据加载进度动态更新。这时必须用 JS 修改 stroke-dashoffset 的实时值,而不是靠 CSS 动画。
典型错误是每帧都 setAttribute 改 stroke-dashoffset,造成 layout thrashing;或者用 requestAnimationFrame 但没做节流,动画卡顿。
- 进度百分比 → 偏移量 =
初始偏移 × (1 - progress)(progress 是 0~1) - 推荐用
style.setProperty()更新 CSS 变量,再由 CSS 计算偏移,避免频繁 DOM 操作 - 加载失败或超时后,记得清除动画 class 并设置最终状态(如红圈 + ❌)
环形动画的“完成感”很依赖结束瞬间的停顿和反馈,光动完就消失,用户会觉得没加载完。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











