stroke-dasharray必须写两个值(如283,0)以避免浏览器自动补全为虚线环;周长需手算取整,stroke-dashoffset负值控制起始点,动画应从283减至0实现顺时针进度。

用 stroke-dasharray 和 stroke-dashoffset 做 SVG 圆形进度条,不是“画一圈再擦掉”,而是“只画一段,然后挪着起点位置露出来”——理解这点,才能避免动画跳变、起始点偏移、进度不准三大坑。
为什么 stroke-dasharray 必须写成两个值,不能只写一个?
浏览器看到 stroke-dasharray: 283 会自动补全为 stroke-dasharray: 283, 283,结果变成虚线环,动画一动就“闪一下”。正确写法是显式指定实线段长度和空白段长度:
-
stroke-dasharray: 283, 0:表示“画满整圈,后面不留空” - 周长必须手算(
2 * Math.PI * r),四舍五入取整(如r=45→283),不能靠 CSS 动态计算 - 别用
getTotalLength()在 JS 里读取再设 —— 首屏渲染时 SVG 还没 layout 完,可能读到 0
stroke-dashoffset 负值怎么理解?动画方向怎么定?
stroke-dashoffset 是“从默认起点往负方向挪多远”,值越大,露出越少。所以动画要从大数往小数变:
- 初始状态:进度 0% →
stroke-dashoffset: 283(完全不可见) - 完成状态:进度 100% →
stroke-dashoffset: 0(整圈可见) - 如果写成正向变化(
0 → 283),动画会反向“收回去”,看起来像倒放 - 起始方向由 SVG
<circle></circle>的默认绘制方向决定(顺时针),不加transform: rotate()就别假设它从 12 点钟方向开始
如何让动画精准对应百分比,且支持动态更新?
纯 CSS 实现动态进度,得靠 CSS 变量 + @keyframes 配合,但关键帧本身不能参数化。稳妥做法是用 JS 控制内联样式:
- 先确保 SVG
<circle></circle>的cx/cy/r固定,周长恒为283 - JS 更新时直接设:
circle.style.strokeDashoffset = 283 - (percent / 100) * 283 - 别用
transition直接过渡stroke-dashoffset—— Safari 旧版有渲染卡顿,建议加will-change: transform或改用transform: translateZ(0)触发硬件加速 - 如果必须纯 CSS,可用
@property(仅 Chrome/Firefox 支持)声明受控变量,但兼容性仍是硬伤
容易被忽略的细节:圆角、描边对齐与抗锯齿
SVG 圆形进度条在高分屏或缩放下边缘发虚,常因描边未对齐像素网格:
- 确保
<svg></svg>的width/height是偶数,viewBox坐标也尽量取整(如viewBox="0 0 100 100") -
<circle></circle>的cx/cy推荐设为半整数(如50.5),避免描边落在像素边界上导致模糊 - 别给
<circle></circle>加stroke-linecap: round—— 它会让首尾多出半径长度的“球头”,破坏环形闭合感 - 如果背景色复杂,用
shape-rendering: crispEdges强制关闭抗锯齿(代价是边缘更生硬)
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











