svg是更稳妥的圆形进度条实现方式,需用两个分别绘制背景环和进度弧,通过stroke-dasharray设为周长、stroke-dashoffset动态计算(=周长×(1−progress))控制显示长度,并配合viewbox、aria属性及深色模式适配确保兼容性与可访问性。

用 SVG 圆环替代 CSS 动画实现精确百分比
纯 CSS 的圆形进度条很难精准控制弧长(尤其在 IE 或旧版 Safari 中),stroke-dasharray 计算易出错,且无法响应式适配不同尺寸单元格。SVG 是更稳妥的选择:它原生支持路径描边、可绑定数据、渲染一致。
关键点在于把圆环画在 <svg></svg> 内,用 <circle></circle> 绘制背景环,再用另一个 <circle></circle> 作为进度弧,通过 stroke-dasharray 和 stroke-dashoffset 控制显示长度:
<svg width="40" height="40" viewbox="0 0 40 40"><circle cx="20" cy="20" r="18" fill="none" stroke="#e0e0e0" stroke-width="4"></circle><circle cx="20" cy="20" r="18" fill="none" stroke="#4caf50" stroke-width="4" stroke-dasharray="113.1" stroke-dashoffset="<computed>"></circle></svg>
113.1 是周长(2 * π * r ≈ 2 * 3.1416 * 18),stroke-dashoffset 值 = 113.1 * (1 - progress)。比如 75% 进度 → offset = 113.1 * 0.25 ≈ 28.3。
- 务必设
viewBox并固定宽高,避免缩放失真 - 不要用
%单位设置r或cx/cy,SVG 内部单位是像素 - 若表格列宽动态变化,SVG 宽高需用 JS 重设或改用 CSS
width: 100%+height: auto配合preserveAspectRatio
在 HTML 表格中内联 SVG 并绑定数据
直接把 SVG 写进 <td> 最简单,但批量渲染时容易重复写死。推荐用模板字符串或 JS 插入(如用 <code>innerHTML 或 insertAdjacentHTML):
function renderProgressCircle(progress) {
const circumference = 2 * Math.PI * 18;
const offset = circumference * (1 - progress);
return `
<svg width="40" height="40" viewbox="0 0 40 40"><circle cx="20" cy="20" r="18" fill="none" stroke="#e0e0e0" stroke-width="4"></circle><circle cx="20" cy="20" r="18" fill="none" stroke="#4caf50" stroke-width="4" stroke-dasharray="${circumference.toFixed(1)}" stroke-dashoffset="${offset.toFixed(1)}"></circle></svg>
`;
}
调用:cell.innerHTML = renderProgressCircle(0.62);。注意 progress 必须是 0–1 的小数,不是百分比数字(别传 62,要传 0.62)。
- 如果后端返回的是整数百分比(如
62),记得除以100转换 - 进度为
0时,stroke-dashoffset等于周长,整个弧不可见;1时 offset 为 0,完整闭合 - 避免在循环中频繁拼接大段 HTML 字符串,大数据量表格建议用
DocumentFragment批量插入
适配深色模式与可访问性
圆环颜色不能只靠视觉区分——色盲用户可能分不清绿色和红色进度条。必须加文字标签或 ARIA 属性:
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
在 <td> 里包裹 SVG 和隐藏文本:<pre class="brush:php;toolbar:false;"><td aria-label="任务完成度:62%">
<span style="display: inline-block; position: relative">
<!-- SVG here -->
<span style="position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); font-size: 12px">62%</span>
</span>
</td></pre>
<p>深色模式下,背景色变暗,<code>#e0e0e0 灰会发亮,#4caf50 绿可能对比不足。建议用 CSS 自定义属性统一管理:
:root {
--progress-bg: #e0e0e0;
--progress-fill: #4caf50;
}
@media (prefers-color-scheme: dark) {
:root {
--progress-bg: #424242;
--progress-fill: #81c784;
}
}
然后 SVG 中的 stroke 改为 var(--progress-bg) 和 var(--progress-fill)。
- 不要仅靠颜色表达状态,62% 这个数值必须可读(屏幕阅读器能获取
aria-label或文本节点) - SVG 内部不支持 CSS 变量?那就用 JS 动态设
setAttribute('stroke', ...) - 圆环直径小于 32px 时,内部百分比文字易糊,建议最小尺寸设为
36px
IE11 兼容性兜底方案
IE11 不支持 stroke-dasharray 在 SVG <circle></circle> 上的动画,且部分 SVG 属性解析异常。如果必须支持 IE11,放弃圆弧,改用 <path></path> 手动绘制四分之一/半圆/满圆路径,或退化为线性进度条:
<div style="width: 40px; height: 4px; background: #e0e0e0; border-radius: 2px"> <div style="height: 100%; width: 62%; background: #4caf50; border-radius: 2px"></div> </div>
这种方案虽不美观,但兼容性好、语义清晰、JS 无依赖。用 class 切换样式比内联 style 更易维护。
- 检测 IE11 的简单方式:
!!window.MSInputMethodContext && !!document.documentMode - 圆环在 IE11 中即使能画出来,
stroke-dashoffset也不会随 JS 更新,必须重绘整个 SVG 节点 - 真正麻烦的不是画不出来,而是动画卡顿+文字对齐偏移——不如提前降级
圆环的数学计算本身不难,难的是在不同缩放、不同主题、不同辅助技术下保持一致表现。别为了“看起来酷”牺牲可读性和稳定性。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










