响应式圆形进度条需用viewbox实现缩放,cx/cy/r基于逻辑坐标系,动态计算周长circumference=2πr并精确设为stroke-dasharray,初始stroke-dashoffset=circumference,用对齐顶部,css仅过渡stroke-dashoffset。

用 SVG 做响应式圆形进度条,核心是让圆环尺寸随容器缩放、进度计算不依赖固定像素值、动画只作用于可插值的属性。关键不在“画圆”,而在“可控裁剪+数学对齐+样式隔离”。
用 viewBox 实现真正响应式缩放
不要写死 width/height 或用 CSS 缩放 SVG——这会导致 stroke-width 变粗或模糊。正确做法是:
- 给
<svg></svg>设置viewBox="0 0 200 200"(数值代表逻辑坐标系,不是像素) - 用 CSS 控制 SVG 的实际显示尺寸,例如
width: 100%; max-width: 150px; - 所有
<circle></circle>的cx、cy、r都基于 viewBox 单位(如cx="100" cy="100" r="90") - 这样无论容器多宽,圆始终居中、比例不变、描边粗细一致
动态算周长,别硬编码
进度是否准确,取决于 stroke-dasharray 和真实周长是否严格一致:
将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
- 公式必须是:
circumference = 2 * Math.PI * r - 若
r = 90,周长就是2 * 3.1415926 * 90 ≈ 565.4867,设为stroke-dasharray="565.4867" - JS 中统一计算并赋值,避免手动四舍五入写成
"565"或"565.5"——小误差会放大成明显跳变 - 初始
stroke-dashoffset设为该周长值,表示 0% 时完全隐藏
起点对齐顶部:用 group 包裹 rotate(-90)
SVG 默认 0° 在正右方,直接画圆环会让进度从右侧开始,不符合直觉:
- 把两个
<circle></circle>(背景环 + 进度环)放进一个<g transform="rotate(-90 100 100)"></g>中 - 旋转中心点写成
rotate(-90 cx cy),和 viewBox 中心一致(如100 100) - 不要只给进度环加 transform —— 背景环不同步会导致视觉错位
- 加上
stroke-linecap="round",让圆环两端呈半圆,接头更自然
CSS 动画只驱动 stroke-dashoffset
平滑过渡靠 CSS,但必须精准控制作用对象:
- 在进度环上直接写内联样式:
style="transition: stroke-dashoffset 0.4s ease-out;" - 绝对不要对
stroke-dasharray加 transition —— 浏览器无法插值离散值,会卡顿或失效 - JS 更新时只改
stroke-dashoffset:offset = circumference * (1 - percent / 100) - 例如 75% 进度:
offset = 565.4867 * 0.25 ≈ 141.37










